我有一个班级:
public abstract class BaseComponent { ... }
在该类的构造函数中,我们订阅了一个事件处理程序,例如
protected ObjectWithEventHandler eventObject { get; private set; }
public BaseComponent (ObjectWithEventHandler obj)
{
eventObject = obj;
eventObject.ChangedEvent += new EventHandler(eventObject_OnChangedEvent );
}
protected void eventObject_OnChangedEvent (object sender, EventArgs e) { ... }
在涉及EventHandler订阅时,是否有任何严格的规则?退订?
提供一些取消订阅EventHandler函数的清理代码是否是一种良好的做法?即实现IDisposable并取消订阅EventHandler呢?
或者我是否过度担心?
答案 0 :(得分:3)
只要暴露事件(eventObject
)的对象是在BaseComponent
类中创建的 - 您可以忽略显式取消订阅,因为它将自动进行GC,但显式取消订阅仍然是一种很好的做法。
但是如果您订阅了注入BaseComponent
的外部对象所暴露的事件,那么您应该在BaseComponent
类和Dispose()
方法中实现IDisposable清理。
答案 1 :(得分:3)
如果您完全控制BaseComponent的使用,并且您知道EventObject的生命周期相对于BaseComponent的生命周期更短或相等*,则可以跳过取消订阅代码。
在所有其他情况下,我会包括它。在这种情况下,实现IDisposable是一种很好的风格。
*)实际上,你将eventObject的生命周期耦合到BaseComponent,所以它不能短,但当它们一起超出范围时它仍然可以相等。
答案 2 :(得分:1)
如果由于BaseComponent派生的类的实例应该存在,则eventObject可能会活得更久,你应该提供一些显式触发取消订阅的方法。否则,您将阻止组件的垃圾收集,因为eventObject包含对它的引用。
实现IDisposable()是一种很好的方法,只要你能确保有一些代码实际调用它。终结器不会调用Dispose(),因为只要订阅了eventObject.ChangedEvent并且eventObject仍处于活动状态,垃圾收集器就不会尝试清理你的组件。