C#事件处理程序订阅管理

时间:2011-10-20 13:38:41

标签: c# event-handling

我有一个班级:

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呢?

或者我是否过度担心?

3 个答案:

答案 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仍处于活动状态,垃圾收集器就不会尝试清理你的组件。