显式事件添加/删除,被误解?

时间:2010-05-27 18:48:48

标签: c# .net events memory-management

我最近一直在研究内存管理,并且一直在研究如何管理事件,现在,我看到了事件订阅的显式添加/删除语法。

我认为这很简单,添加/删除只允许我在订阅和取消订阅时执行其他逻辑?我得到它了,还是有更多呢?

此外,当我在这里时,任何有关清理事件处理的建议/最佳做法。

3 个答案:

答案 0 :(得分:13)

添加/删除属性与使用其他成员的set / get属性的逻辑基本相同。 它允许您在注册事件时创建一些额外的逻辑,并封装事件本身。

为什么你想要这样做的一个很好的例子就是在不需要时停止额外的计算(没有人在听这个事件)。

例如,假设事件是由计时器触发的,如果没有人注册事件,我们不希望计时器工作:

private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent 
{
   add 
   { 
       if (_explicitEvent == null) timer.Start();
       _explicitEvent += value; 
   } 
   remove 
   { 
      _explicitEvent -= value; 
      if (_explicitEvent == null) timer.Stop();
   }
}

你可能想要用对象锁定添加/删除(事后的想法)......

答案 1 :(得分:8)

是的,添加/删除语法允许您实现自己的订阅逻辑。当您将它们遗漏(事件的标准符号)时,编译器会生成标准实现。这就像自动属性。

在下面的示例中,Event1和Event2之间没有真正的区别。

public class Foo  
{ 
  private EventHandler handler; 
  public event EventHandler Event1 
  { 
    add { handler += value; } 
    remove { handler -= value; } 
  } 

  public event EventHandler Event2;  
}

但这是与“清理”处理程序不同的主题。订阅类应该取消订阅。出版课对这方面无能为力 想象一个可以“清理”其事件订阅列表的类。只有在Disposed本身时它才能明智地做到这一点,然后它不太可能有效率,因为Disposed类通常在处理后不久就可以收集。

答案 2 :(得分:3)

添加/删除语法通常用于将事件实现“转发”到另一个类。

清理订阅(不是“事件句柄”)最好通过实施IDisposable来完成。

更新:哪个对象应该实现IDisposable存在一些变化。 Rx团队从设计角度做出了最佳决策:订阅本身是IDisposable。常规.NET事件没有表示订阅的对象,因此选择在发布者(定义事件的类)和订阅者(​​通常是包含要订阅的成员函数的类)之间。虽然我的设计本能更喜欢订阅者IDisposable,但大多数真实世界的代码都会使发布者IDisposable:这是一个更简单的实现,并且可能存在没有实际订阅者实例的情况。

(也就是说,如果代码实际上清理了事件订阅。大多数代码都没有。)