Quá tải toán tử bằng
Thực tế, có một sự khác biệt về ngữ nghĩa giữa hai so sánh khi bạn so sánh null
với một loại đã quá tải ==
toán tử. foo is null
sẽ sử dụng so sánh tham chiếu trực tiếp để xác định kết quả, trong khi đó foo == null
tất nhiên sẽ chạy ==
toán tử quá tải nếu nó tồn tại.
Trong ví dụ này, tôi đã giới thiệu một "lỗi" trong ==
toán tử bị quá tải , khiến nó luôn luôn ném một ngoại lệ nếu đối số thứ hai là null
:
void Main()
{
Foo foo = null;
if (foo is null) Console.WriteLine("foo is null"); // This condition is met
if (foo == null) Console.WriteLine("foo == null"); // This will throw an exception
}
public class Foo
{
public static bool operator ==(Foo foo1, Foo foo2)
{
if (object.Equals(foo2, null)) throw new Exception("oops");
return object.Equals(foo1, foo2);
}
// ...
}
Mã IL để foo is null
sử dụng ceq
hướng dẫn để thực hiện so sánh tham chiếu trực tiếp:
IL_0003: ldloc.0 // foo
IL_0004: ldnull
IL_0005: ceq
Mã IL để foo == null
sử dụng lệnh gọi đến toán tử quá tải:
IL_0016: ldloc.0 // foo
IL_0017: ldnull
IL_0018: call UserQuery+Foo.op_Equality
Vì vậy, sự khác biệt là, nếu bạn sử dụng, ==
bạn có nguy cơ chạy mã người dùng (có thể có khả năng có vấn đề về hành vi hoặc hiệu suất không mong muốn).
Hạn chế về thuốc generic
Sử dụng is null
cấu trúc giới hạn kiểu cho kiểu tham chiếu. Trình biên dịch đảm bảo điều này, có nghĩa là bạn không thể sử dụng is null
trên một loại giá trị. Nếu bạn có một phương thức chung, bạn sẽ không thể sử dụng is null
trừ khi loại chung bị ràng buộc là loại tham chiếu.
bool IsNull<T>(T item) => item is null; // Compile error: CS0403
bool IsNull<T>(T item) => item == null; // Works
bool IsNull<T>(T item) where T : class => item is null; // Works
Cảm ơn David Augusto Villa đã chỉ ra điều này.