C# EventHandler如何知道仅在定义类时才允许=运算符?

C# EventHandler如何知道仅在定义类时才允许=运算符?,c#,event-handling,C#,Event Handling,我从一个问题开始,在键入问题时找到了答案,但我认为这可能有助于a)获得确认,B)帮助他人 如果我有一个事件,并且应用程序中的几个地方添加了侦听器,那么一次删除所有侦听器的最佳方法是什么?例如,我可以 myPage.OnPageOpened += OpenPage; 后来在我的代码中 myPage.OnPageOpened -= OpenPage; 但如果我有未知的第三方订户,我想按下一个神奇的重置按钮,清除一切,从头开始呢 您可以对EventHandler在任何位置使用+=和-=运算符,因为

我从一个问题开始,在键入问题时找到了答案,但我认为这可能有助于a)获得确认,B)帮助他人

如果我有一个事件,并且应用程序中的几个地方添加了侦听器,那么一次删除所有侦听器的最佳方法是什么?例如,我可以

myPage.OnPageOpened += OpenPage;
后来在我的代码中

myPage.OnPageOpened -= OpenPage;
但如果我有未知的第三方订户,我想按下一个神奇的重置按钮,清除一切,从头开始呢

您可以对EventHandler在任何位置使用+=和-=运算符,因为运算符重载是公共的。=重载运算符是私有的,它只能在定义类中调用

因此,在定义类中,我可以使用它来清除EventHandler

OnPageOpened = null;
为了展示这个功能,我可以

public void ClearPageOpenedEvents() {
   OnPageOpened = null;
}

这是正确的吗?

这样做是正确的,但是类之外的东西怎么知道类应该删除所有事件侦听器呢?如果有人正在扩展/使用您的代码,并期望该事件持续发生,该怎么办?

是的,您是正确的。原因是编译器在封面下创建了一个
private
委托
对象,如下所示:

private EventHandler pageOpened;

public EventHandler PageOpened
{
    add { pageOpened += value; }
    remove { pageOpened -= value; }
}

在您的类中,您有一个对private
delegate
实例的引用,因此您可以执行赋值。如果这是您需要的功能,那么您肯定希望公开一种方法来清除目标;您不想公开代理本身。

您可以在事件上使用赋值运算符,因为添加和删除事件就是这样工作的。使用Reflector可以清楚地了解C#中的事件是如何完成的

考虑到

public class MyClass
{
  public event EventHandler MyEvent;
}
编译时生成以下代码

public class MyClass
{
  private EventHandler MyEvent;

  public event EventHandler MyEvent;
}
因此,当您引用
MyEvent
时,您引用的是私有委托变量
MyEvent
+=
-=
运算符是“特殊的”(因为它们不是运算符),并被更改为调用为事件创建的
添加
删除
方法(它们本身使用赋值运算符)


如果我安装/打开了反射器,这会更快/更容易发现。在重置期间,游戏将重新开始。我同意公共ClearPageOpenedEvents()不是正常情况,应该谨慎使用。并且应该(至少在我的情况下)是内部的,而不是公共的。也许您可以处置您的对象并创建新的对象。这也将确保你从一个干净的状态开始。清理还有一个优点,即在扩展类时不会错过需要清除的事件处理程序。
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_MyEvent(EventHandler value)
{
  this.MyEvent = (EventHandler) Delegate.Combine(this.MyEvent, value);
}

[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_MyEvent(EventHandler value)
{
    this.MyEvent = (EventHandler) Delegate.Remove(this.MyEvent, value);
}