Bộ câu hỏi phỏng vấn C#/.Net phần 5

Extension Method trong C# là gì và cách sử dụng chúng?


Các extension method (phương thức mở rộng) cho phép bạn thêm các phương thức vào các kiểu hiện có mà không cần tạo một kiểu dẫn xuất mới, biên dịch lại hoặc sửa đổi kiểu gốc. Extension method là một loại phương thức static đặc biệt, nhưng chúng được gọi như thể chúng là các phương thức instance trên kiểu mở rộng.

namespace ExtensionMethods
{
   public static class MyExtensions
   {
      public static int WordCount(this String str)
      {
         return str.Split(new char[] { ' ', '.', '?' },
         StringSplitOptions.RemoveEmptyEntries).Length;
      }
    }
}

Lớp sealed trong C# là gì?


  • Khi một lớp được định nghĩa là một lớp sealed, thì lớp đó không thể được kế thừa.
  • Các struct cũng được sealed.

Reflection trong C#.Net là gì?


Reflection là khả năng truy vấn và tương tác với hệ thống kiểu theo cách động (dynamic way). Nói chung, Reflection cho phép bạn truy cập vào metadata (siêu dữ liệu) về các đối tượng. Ví dụ, bạn có thể tải một DLL và xác định xem nó có chứa phần triển khai của một giao diện hay không. Bạn có thể sử dụng điều này để khám phá các dll hỗ trợ chức năng trong runtime. Bạn có thể sử dụng reflection để mở rộng một ứng dụng mà không cần biên dịch lại và không cần phải khởi động lại.

Sự khác biệt giữa constant và readonly là gì?


Ngoài sự khác biệt rõ ràng là

  • Phải khai báo giá trị tại thời điểm định nghĩa cho một const so với các giá trị readonly có thể được tính toán động nhưng cần được gán trước khi phương thức khởi tạo thoát ra ... sau đó nó bị đóng băng (frozen).
  • const là hoàn toàn static. Bạn sử dụng ký hiệu ClassName.ConstantName để truy cập chúng.

Còn có một sự khác biệt tinh tế, hãy xem xét lớp được định nghĩa trong AssemblyA.

public class Const_V_Readonly
{
   public const int I_CONST_VALUE = 2;
   public readonly int I_RO_VALUE;
   public Const_V_Readonly()
   {
      I_RO_VALUE = 3;
   }
}

AssemblyB tham chiếu đến AssemblyA và sử dụng các giá trị này trong mã. Khi điều này được biên dịch,

  • Trong trường hợp của giá trị const, nó giống như một tìm kiếm thay thế (find-replace), giá trị 2 được 'đưa vào' IL của AssemblyB. Điều này có nghĩa là nếu ngày mai, chúng ta cập nhật I_CONST_VALUE trong AssemblyA thành 20, thì I_CONST_VALUE trong AssemblyB vẫn là 2 cho đến khi chúng ta biên dịch lại nó.
  • Trong trường hợp của giá trị readonly, nó giống như một tham chiếu đến một vị trí bộ nhớ. Giá trị không được đưa vào IL của AssemblyB. Điều này có nghĩa là nếu vị trí bộ nhớ được cập nhật, AssemblyB sẽ nhận được giá trị mới mà không cần biên dịch lại. Vì vậy, nếu I_RO_VALUE được cập nhật thành 30, bạn chỉ cần build AssemblyA. Tất cả các client không cần phải được biên dịch lại.

Hãy nhớ rằng nếu bạn tham chiếu một const từ một assembly khác, giá trị của nó sẽ được biên dịch ngay trong assembly đang gọi. Bằng cách đó, khi bạn cập nhật const trong assembly được tham chiếu, nó sẽ không thay đổi trong assembly đang gọi!

Giải thích quá trình biên dịch mã trong C#?


Có bốn bước trong quá trình biên dịch mã bao gồm:

  • Biên dịch mã nguồn thành Managed code bởi trình biên dịch C#.
  • Kết hợp mã mới tạo thành các assembly.
  • Tải Common Language Runtime(CLR).
  • Thực thi assembly bằng CLR

Phạm vi của biến thành viên Internal của một lớp C# là gì?


Internal access specifier cho phép một lớp hiển thị các biến thành viên và các hàm thành viên của nó với các hàm và đối tượng khác trong assembly hiện tại. Nói cách khác, bất kỳ thành viên nào với internal access specifier đều có thể được truy cập từ bất kỳ lớp hoặc phương thức nào được định nghĩa trong cùng ứng dụng.

public class BaseClass
{
   // Only accessible within the same assembly.
   internal static int x = 0;
}

Bạn có thể sử dụng nó cho các lớp/phương thức tiện ích hoặc trợ giúp mà bạn muốn truy cập từ nhiều lớp khác trong cùng một assembly, nhưng bạn muốn đảm bảo mã trong các assembly khác không thể truy cập.

Hàm anonymous trong C# là gì?


Hàm anonymous (hàm ẩn danh) là một câu lệnh hoặc biểu thức "nội tuyến" có thể được sử dụng ở bất cứ nơi nào mong đợi một kiểu delegate. Bạn có thể sử dụng nó để khởi tạo một delegate đã đặt tên hoặc truyền nó làm tham số phương thức.

Có hai loại hàm anonymous:

Lambda Expressions (biểu thức Lambda)
Anonymous Methods (phương thức ẩn danh)
// Original delegate syntax required
// initialization with a named method.
TestDelegate testDelA = new TestDelegate(M);

// C# 2.0: A delegate can be initialized with
// inline code, called an "anonymous method." This
// method takes a string as an input parameter.
TestDelegate testDelB = delegate(string s) {
   Console.WriteLine(s);
};

// C# 3.0. A delegate can be initialized with
// a lambda expression. The lambda also takes a string
// as an input parameter (x). The type of x is inferred by the compiler.
TestDelegate testDelC = (x) => {
   Console.WriteLine(x);
};

// Invoke the delegates.
testDelA("Hello. My name is M and I write lines.");
testDelB("That's nothing. I'm anonymous and ");
testDelC("I'm a famous author.");

Marshalling là gì và tại sao chúng ta cần nó?


Bởi vì các ngôn ngữ và môi trường khác nhau có các quy ước gọi khác nhau, các quy ước bố cục khác nhau, các kích thước primitive khác nhau (ví dụ char trong C# và char trong C), các quy ước tạo / hủy đối tượng khác nhau và các hướng dẫn thiết kế khác nhau. Bạn cần một cách để đưa những thứ từ môi trường được quản lý vào một nơi nào đó mà môi trường không được quản lý có thể nhìn thấy và hiểu nó và ngược lại. Đó là những gì mà Marshalling thực hiện.

Marshaling là quá trình tạo cầu nối giữa managed code và unmanaged code, Marshalling là một trong những dịch vụ quan trọng nhất do CLR cung cấp.

Sự khác biệt giữa phương thức dispose và finalize là gì trong C#?


Cả hai Finalize và Dispose đều được sử dụng cho cùng một nhiệm vụ giải phóng unmanaged resource (tài nguyên không được quản lý) nhưng có một số điểm khác biệt.

Finalize:

  • Finalize được sử dụng để giải phóng các unmanaged resource không được sử dụng như tệp, kết nối cơ sở dữ liệu trong miền ứng dụng, ... được giữ bởi một đối tượng trước khi đối - tượng đó bị phá hủy.
  • Trong quy trình nội bộ (Internal process), nó được gọi bởi Garbage Collector và không thể gọi thủ công bằng mã người dùng hoặc bất kỳ service nào.
  • Finalize thuộc về lớp System.Object.
  • Triển khai nó khi bạn có unmanaged resource trong mã của mình và đảm bảo rằng những tài nguyên này được giải phóng khi quá trình thu gom rác diễn ra.

Dispose:

  • Dispose cũng được sử dụng để giải phóng các unmanaged resource không được sử dụng như tệp, kết nối cơ sở dữ liệu trong miền ứng dụng bất cứ lúc nào.
  • Dispose được gọi thủ công bằng mã người dùng một cách rõ ràng.
  • Nếu chúng ta cần phương thức dispose thì phải triển khai lớp đó bằng IDisposable interface.
  • Dispose thuộc về IDisposable interface.
  • Triển khai dispose khi bạn đang viết một custom class để được sử dụng bởi những người dùng khác.

Sự khác biệt giữa late binding và early binding trong C#?


  • Trong Compile time polymorphism (đa hình thời gian biên dịch) hay gọi là Early Binding (liên kết sớm), chúng ta sẽ sử dụng nhiều phương thức có cùng tên nhưng khác tham số, bởi vì điều này mà chúng ta có thể thực hiện các tác vụ khác nhau với cùng một tên phương thức trong cùng một lớp và nó được gọi là Method overloading.
  • Run time polymorphism (đa hình thời gian chạy) còn được gọi là Late Binding (liên kết muộn). Trong Late Binding, chúng ta có thể sử dụng cùng một tên phương thức với cùng chữ ký có nghĩa là cùng kiểu hoặc cùng số lượng tham số nhưng không cùng lớp vì trình biên dịch không cho phép điều đó tại thời điểm biên dịch, vì vậy chúng ta có thể sử dụng trong lớp kế thừa liên kết tại runtime khi một đối tượng của lớp con hoặc lớp kế thừa được khởi tạo, đó là cách chúng ta nói rằng Late Binding còn được gọi là Method overriding.

Constructor Chaining trong C# là gì?


Constructor Chaining là một cách tiếp cận mà một phương thức khởi tạo (constructor) gọi một phương thức khởi tạo khác trong cùng một lớp cơ sở hoặc lớp cơ sở. Điều này rất hữu ích khi chúng ta có một lớp định nghĩa nhiều phương thức khởi tạo.

class Foo {
   private int id;
   private string name;

   public Foo() : this(0, "") {
   }

   public Foo(int id) : this(id, "") {
   }

   public Foo(string name) : this(0, name) {
   }

   public Foo(int id, string name) {
      this.id = id;
      this.name = name;
   }
}

Sự khác biệt giữa toán tử is và as trong C# là gì?


Toán tử is kiểm tra xem một đối tượng có thể được ép thành một kiểu cụ thể hay không.

if (someObject is StringBuilder) ...

Toán tử as cố gắng ép một đối tượng thành một kiểu cụ thể và trả về null nếu nó không thành công.

StringBuilder b = someObject as StringBuilder;
if (b != null) ...

Bạn có thể tạo một hàm trong C# có thể chấp nhận số lượng đối số khác nhau không?


Bằng cách sử dụng từ khóa params, bạn có thể chỉ định một tham số của phương thức nhận một số lượng đối số thay đổi. Không có tham số bổ sung nào khác được phép sau từ khóa params trong khai báo phương thức và chỉ một từ khóa params được phép trong khai báo phương thức. Kiểu khai báo của tham số params phải là mảng một chiều.

public static void UseParams(params int[] list) {
   for (int i = 0; i < list.Length; i++) {
      Console.Write(list[i] + " ");
   }
   Console.WriteLine();
}

public static void UseParams2(params object[] list) {
   for (int i = 0; i < list.Length; i++) {
      Console.Write(list[i] + " ");
   }
   Console.WriteLine();
}

// usage
UseParams(1, 2, 3, 4);
UseParams2(1, 'a', "test");

(senior)

Operator overloading (nạp chồng toán tử) có được hỗ trợ trong C# không?


Kiểu do người dùng xác định có thể nạp chồng toán tử được xác định trước trong C#. Có nghĩa là, một kiểu có thể cung cấp triển khai tùy chỉnh của một toán tử trong trường hợp một hoặc cả hai toán hạng thuộc kiểu đó.

public static Box operator+ (Box b, Box c) {
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   return box;
}

Hàm trên thực hiện toán tử cộng (+) cho một lớp Box do người dùng định nghĩa. Nó thêm các thuộc tính của hai đối tượng Box và trả về đối tượng Box kết quả.

Avatar Techmely Team
VIẾT BỞI

Techmely Team