[英]Difference between two different types of assigning events to event handlers
我在SO中看到了這個示例代碼,它說一個練習很糟糕而另一個很好。 但我不明白為什么? 事實上,我得到了那個着名的RCW COM對象錯誤,該帖子說這可能是一個原因。
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
編輯:這是源的鏈接: 不能使用已與其基礎RCW分離的COM對象
我認為這兩個代碼片段是相同的,我們在這里沒有強/弱引用的任何問題。
首先,如果我們的Interop.ComObjectWrapper
提供CLR事件(即在Interop.ComObjectWrapper
中存儲事件處理程序的事件),我們肯定會從ComObjectWrapper
到我們的對象獲得強引用。
任何代表包含兩個部分: Target
類型的object
和方法指針以特定的方法。 如果Target
為null
,則回調指向靜態方法。
不可能有一個類型為WeakReference的 Target
的委托。 有所謂的弱事件模式,但它實現在EventManager之上而不是普通的委托。
內部事件實現意味着在訂閱事件之后:
comObject.SomeEvent += EventCallback;
comObject
對象隱含地擁有對SomeClass
對象的強引用。 無論您使用何種訂閱技術以及ComObject是否是COM對象包裝器,這都是正確的。
訂閱事件會在生命周期中添加兩個對象之間的隱式依賴關系。 這就是為什么.NET世界中最常見的內存泄漏是由訂閱長期存在的對象的事件引起的。 在應用程序中可訪問事件持有者之前,事件訂閱者不會死
但事件如果我的假設不正確並且ComObjectWrapper
提供了一些弱事件模式的概念,那么在字段中保存事件處理程序將無濟於事。
讓我們回顧一下event關鍵字的含義:
private event ComEventHandler comEventHandler;
...
comEventHandler = new ComEventHandler(EventCallback);
在當前字段中保存回調(基本上我們可以將私有事件視為簡單的委托字段)不會更改現有行為。
我們已經知道委托是一個簡單的對象,它存儲對Target對象(即SomeClass
對象)和方法(即public void EventCallBack()
)的public void EventCallBack()
。 這意味着在字段中存儲附加委托會從SomeClass
本身添加對SomeClass
附加引用。
基本上,在字段中存儲事件處理程序在語義上等同於在SomeClass中存儲附加引用:
private SomeClass someClass;
public SomeClaas(){//這與在comEventHandler字段中存儲委托//基本相同someClass = this; }
在SomeClass
存儲強引用不會延長當前對象的生命周期。 這意味着,如果ComObjectWrapper
不會抱持着強烈的參考SomeClass
對象存儲事件處理程序在comEventHandler
不會延長SomeClass的一生並不會阻止SomeClass
收集垃圾。
在私有字段中存儲事件處理程序不會延長對象的生命周期,也不會阻止它進行垃圾回收。
這就是為什么以下代碼片段在對象生存期方面沒有區別:
// GOOD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// EVEN BETTER!
comObject.SomeEvent += EventCallback;
// NOT GOOD, BECAUSE WAN'T HELP!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.