【问题标题】:C# Event handler subscription managementC# 事件处理程序订阅管理
【发布时间】:2011-10-20 13:38:40
【问题描述】:

我有一堂课:

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 取消订阅函数的清理代码是否被认为是一种好习惯? IE。那么实现IDisposable并取消订阅EventHandler呢?

还是我过度担心?

【问题讨论】:

  • 我很确定你不需要担心这个。当您的实例被垃圾回收时,C# 应该清除所有事件引用(即不再在范围内,或者该实例不再在其他任何地方引用)
  • @musefan,这个故事有点复杂:你需要考虑所涉及对象的生命周期。

标签: c# event-handling


【解决方案1】:

如果您完全控制了 BaseComponent 的使用,并且您知道 EventObject 的生命周期比 BaseComponent 的生命周期更短或相等*,您可以跳过取消订阅代码。

在所有其他情况下,我都会包含它。在这种情况下,实现 IDisposable 是一种很好的方式。

*) 实际上,您将 eventObject 的生命周期与 BaseComponent 耦合,因此它的生命周期不能更短,但当两者一起超出范围时,它仍然可以相等。

【讨论】:

    【解决方案2】:

    只要在 BaseComponent 类中创建暴露事件 (eventObject) 的对象 - 您可以忽略显式取消订阅,因为它会自动 GC,但显式取消订阅无论如何都是一个好习惯。

    但如果您订阅的事件由注入BaseComponent 的外部对象公开,您应该在BaseComponent 类中实现IDisposable,并在Dispose() 方法中进行清理。

    【讨论】:

      【解决方案3】:

      如果从 BaseComponent 派生的类的实例应该存在,则 eventObject 可能存在更长的时间,您应该提供某种方式来显式触发取消订阅。否则你会阻止你的组件的垃圾收集,因为 eventObject 持有对它的引用。

      实现 IDisposable() 是完成此任务的好方法,只要您可以确保有一些代码实际调用它。终结器不会调用 Dispose(),因为垃圾收集器不会尝试清理您的组件,只要它订阅了 eventObject.ChangedEvent 并且 eventObject 仍然存在。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-15
        • 2021-03-29
        • 1970-01-01
        相关资源
        最近更新 更多