如何在C#中清除事件订阅?

pro*_*mer 137 .net c# events delegates

参加以下C#课程:

c1 {
 event EventHandler someEvent;
}
Run Code Online (Sandbox Code Playgroud)

如果有很多订阅c1someEvent事件,我想清除所有这些,那么实现这一目标的最佳方法是什么?还要考虑对此事件的订阅可以是lambdas/anonymous delegates.

目前我的解决方案是添加一个ResetSubscriptions()方法,将c1其设置someEvent为null.我不知道这是否有任何看不见的后果.

Jon*_*eet 176

在类中,您可以将(hidden)变量设置为null.空引用是有效地表示空调用列表的规范方式.

从课外,你不能这样做 - 事件基本上暴露"订阅"和"取消订阅",就是这样.

值得注意的是,类似字段的事件实际上是在做什么 - 它们同时创建变量事件.在类中,您最终引用变量.从外面,您可以参考该活动.

有关更多信息,请参阅我关于事件和代理的文章.

  • 哦面向对象编程的奇迹. (10认同)
  • 如果你很顽固,你可以通过反思强制它.请参见http://stackoverflow.com/questions/91778/how-to-remove-all-event-handlers-from-a-control/91853#91853. (3认同)

pro*_*mer 32

向c1添加一个方法,将'someEvent'设置为null ...

class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = null;}
}
Run Code Online (Sandbox Code Playgroud)


小智 7

class c1
{
    event EventHandler someEvent;
    ResetSubscriptions() {someEvent = delegate{};}
}
Run Code Online (Sandbox Code Playgroud)

使用委托{}比使用null更好

  • 为什么?你能扩展一下这个答案吗? (2认同)
  • 鉴于您可以在现代 C# 中执行 `someEvent?.Invoke(...)`,我不确定这是否重要,或者使用 noop 委托的稍微缺乏清晰度是否值得。 (2认同)

Jon*_*son 6

在类中将事件设置为null有效.当你处理一个类时,你应该总是将事件设置为null,GC有事件问题,如果它有悬空事件,可能不会清理已处理的类.


Car*_*ary 6

清除所有订阅者的最佳做法是,如果要将此功能公开给外部,可以通过添加另一个公共方法将someEvent设置为null.这没有任何看不见的后果.前提条件是记住使用关键字"event"声明SomeEvent.

请参阅书籍 - 简言之C#4.0,第125页.

这里有人建议使用Delegate.RemoveAll方法.如果您使用它,示例代码可以遵循以下形式.但这真的很愚蠢.为什么不只是SomeEvent=null里面ClearSubscribers()的功能?

   public void ClearSubscribers ()
    {
          SomeEvent = (EventHandler) Delegate.RemoveAll(SomeEvent, SomeEvent);// Then you will find SomeEvent is set to null.
    }
Run Code Online (Sandbox Code Playgroud)


Mic*_*cah 5

您可以使用Delegate.Remove或Delegate.RemoveAll方法来实现此目的.

  • 我不相信这将适用于lambda表达式或匿名委托. (6认同)