Tất cả đều được coi là: khi hai đại biểu được coi là giống nhau cho mục đích cộng/trừ đại biểu. Khi bạn hủy đăng ký, về cơ bản nó sử dụng logic từ Delegate.Remove
, xem xét hai đại biểu tương đương nếu cả hai .Target
và trận đấu .Method
(ít nhất, đối với trường hợp đơn giản của một đại biểu với một phương pháp đích duy nhất; . Vì vậy: .Method
và .Target
trên lambda là gì (giả sử chúng tôi đang biên dịch nó thành một số đại biểu và không hiển thị biểu thức)?
Trình biên dịch thực sự có rất nhiều tự do ở đây, nhưng những gì xảy ra là:
- nếu lambda bao gồm một đóng cửa hơn một tham số hoặc biến, trình biên dịch tạo ra một phương pháp (các phương pháp) trên một lớp trình biên dịch tạo ra đại diện cho bối cảnh chụp (cũng có thể bao gồm mã thông báo
this
); mục tiêu là tham chiếu đến trường hợp chụp ngữ cảnh này (được xác định bởi phạm vi chụp)
- nếu lambda không bao gồm đóng trên một tham số hoặc biến, nhưng sử dụng trạng thái mỗi trường hợp qua
this
(ẩn hoặc rõ ràng), trình biên dịch tạo ra một phương thức cá thể (phương thức ) trên loại hiện tại; các mục tiêu là trường hợp hiện tại (this
)
- nếu không trình biên dịch tạo ra một phương pháp tĩnh (phương pháp ), và mục tiêu là null (tình cờ, trong trường hợp này nó cũng bao gồm một lĩnh vực thuận tiện để cache một đơn đại biểu dụ tĩnh - vì vậy trong kịch bản này, chỉ có một đại biểu được từng được tạo ra mỗi lambda)
gì nó không làm, tuy nhiên, là so sánh rất nhiều lambdas với các cơ quan tìm kiếm tương tự để giảm bất kỳ . Vì vậy, những gì tôi nhận được khi tôi biên dịch mã của bạn là hai phương pháp tĩnh:
[CompilerGenerated]
private static void <Main>b__0(object s, string e)
{
Console.WriteLine("Bark: {0}", e);
}
[CompilerGenerated]
private static void <Main>b__2(object s, string e)
{
Console.WriteLine("Bark: {0}", e);
}
(các Main
đây chỉ là bởi vì trong giàn khoan thử nghiệm của tôi những lambdas là bên trong phương pháp Main
- nhưng cuối cùng trình biên dịch có thể chọn bất kỳ phát thành âm thanh tên nó chọn ở đây)
Phương pháp đầu tiên được sử dụng bởi lambda đầu tiên; phương pháp thứ hai được sử dụng bởi lambda thứ hai.Vì vậy, cuối cùng, lý do nó không hoạt động là vì .Method
không khớp.
Trong thường xuyên C# điều khoản, nó sẽ giống như thực hiện:
obj.SomeEvent += MethodOne;
obj.SomeEvent -= MethodTwo;
nơi MethodOne
và MethodTwo
có cùng mã bên trong chúng; nó không hủy đăng ký bất cứ điều gì.
Nó có thể là đẹp nếu trình biên dịch phát hiện này, nhưng nó là không phải, và như vậy nó là an toàn hơn mà nó không đắc cử tới - nó có thể có nghĩa là trình biên dịch khác nhau bắt đầu sản xuất rất các kết quả khác nhau.
Là một lưu ý phụ; nó có thể rất khó hiểu nếu nó đã làm cố gắng để de-dup, bởi vì bạn cũng sẽ có vấn đề của bối cảnh chụp - nó sẽ là trường hợp nó "làm việc" trong một số trường hợp và không phải những người khác - - có lẽ là kịch bản tồi tệ nhất có thể.
http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c-sharp –
Có, điều này phác thảo giống như những gì trong bài viết nhưng nó không giải thích tại sao. – DaveDev
@TimSchmelter không may trình duyệt của tôi chỉ có thể xem trong quá khứ. – DaveDev