Tôi đã luôn luôn nghĩ rằng nó không thể cho this
để được null bên trong cơ thể phương pháp dụ. Sau chương trình đơn giản chứng minh rằng nó là có thể. Đây có phải là một số hành vi được ghi lại không?this == null bên trong .NET instance method - tại sao điều đó lại có thể?
class Foo
{
public void Bar()
{
Debug.Assert(this == null);
}
}
public static void Test()
{
var action = (Action)Delegate.CreateDelegate(typeof (Action), null, typeof(Foo).GetMethod("Bar"));
action();
}
CẬP NHẬT
Tôi đồng ý với câu trả lời nói rằng đó là cách phương pháp này được ghi chép lại. Tuy nhiên, tôi không thực sự hiểu hành vi này. Đặc biệt là vì nó không phải là cách C# được thiết kế.
Chúng tôi đã nhận được một báo cáo từ ai đó (có khả năng một trong những nhóm NET sử dụng C# (nghĩ rằng nó vẫn chưa được đặt tên C# tại thời điểm đó)) ai có mã bằng văn bản rằng gọi một phương thức trên một null con trỏ, nhưng họ đã không nhận được một ngoại lệ bởi vì phương pháp đã không truy cập bất kỳ lĩnh vực (tức là "này" là null, nhưng không có gì trong phương pháp được sử dụng nó). Phương pháp đó sau đó được gọi là một phương pháp khác đã sử dụng điểm này và ném một ngoại lệ , và một chút đầu gãi xảy ra sau đó. Sau khi họ tìm thấy nó , họ đã gửi cho chúng tôi một lưu ý về nó. Chúng tôi nghĩ rằng có thể gọi một phương thức trên một cá thể rỗng là một bit lạ . Peter Golde đã làm một số thử nghiệm để xem những gì tác động perf là luôn luôn sử dụng callvirt, và nó là đủ nhỏ mà chúng tôi quyết định để thực hiện thay đổi.
http://blogs.msdn.com/b/ericgu/archive/2008/07/02/why-does-c-always-use-callvirt.aspx
Xem câu trả lời của tôi cho thấy CLR được thiết kế cố ý như thế này đã có trong .NET 1.0.Bài báo bạn trích dẫn là về một tình huống khác (không ủy nhiệm), đó sẽ là một tối ưu hóa trình biên dịch - thay thế một 'callvirt' bằng một cuộc gọi trực tiếp khi loại cá thể có thể được xác định tĩnh. Lưu ý rằng lý do tại sao CLR phải ném 'NullReferenceException' trong' callvirt' là cần tìm kiếm VMT dựa trên tham chiếu 'this'; không chỉ là một mong muốn ngữ nghĩa để kiểm tra các tài liệu tham khảo. –
Related: http://stackoverflow.com/q/3143498/158779 –
IMHO, thật không may là không có cách tiêu chuẩn (có lẽ thông qua các thuộc tính) để xác định rằng một phương thức nên được gọi với 'call' thay vì' callvirt', vì có thể cho phép các loại đóng gói các giá trị [như 'string'] để có các thành viên có thể hoạt động trên các vị trí lưu trữ có giá trị mặc định. Nói 'if (someString.IsNullOrEmpty)' sẽ là IMHO sạch hơn nhiều so với 'if (String.IsNullOrEmpty (someString))'. – supercat