(Để biết thông tin về trình trợ giúp ngoại lệ mới trong Visual Studio 2017, hãy xem phần cuối của câu trả lời này)
Hãy xem xét mã này:
String s = null;
Console.WriteLine(s.Length);
Điều này sẽ ném một NullReferenceException
vào dòng thứ hai và bạn muốn biết tại sao .NET không cho bạn biết rằng nó s
là null khi ngoại lệ được ném.
Để hiểu tại sao bạn không nhận được thông tin đó, bạn nên nhớ rằng nó không phải là nguồn C # thực thi mà là IL:
IL_0001: ldnull
IL_0002: stloc.0 // s
IL_0003: ldloc.0 // s
IL_0004: callvirt System.String.get_Length
IL_0009: gọi System.Console.WriteLine
Nó là callvirt
opcode ném NullReferenceException
và nó thực hiện điều đó khi đối số đầu tiên trên ngăn xếp đánh giá là một tham chiếu rỗng (tham chiếu đã được tải bằng cách sử dụng ldloc.0
).
Nếu .NET có thể nói rằng đó là s
tham chiếu rỗng, theo một cách nào đó, nó sẽ theo dõi đối số đầu tiên trên biểu mẫu bắt nguồn của ngăn xếp đánh giá s
. Trong trường hợp này, chúng ta dễ dàng thấy rằng đó là s
null nhưng nếu giá trị đó là giá trị trả về từ một lệnh gọi hàm khác và không được lưu trữ trong bất kỳ biến nào? Dù sao, loại thông tin này không phải là thứ bạn muốn theo dõi trong một máy ảo như máy ảo .NET.
Để tránh vấn đề này, tôi khuyên bạn nên thực hiện kiểm tra đối số null trong tất cả các lệnh gọi phương thức công khai (tất nhiên trừ khi bạn cho phép tham chiếu null):
public void Foo(String s) {
if (s == null)
throw new ArgumentNullException("s");
Console.WriteLine(s.Length);
}
Nếu null được truyền cho phương thức, bạn sẽ nhận được một ngoại lệ mô tả chính xác vấn đề là gì (đó s
là null).
Bốn năm sau, Visual Studio 2017 hiện có một trình trợ giúp ngoại lệ mới sẽ cố gắng cho biết những gì là null khi một NullReferenceException
được ném. Nó thậm chí có thể cung cấp cho bạn thông tin cần thiết khi nó là giá trị trả về của một phương thức là null:

Lưu ý rằng điều này chỉ hoạt động trong bản dựng GỠ LỖI.