如何安全地发射事件

当事件没有订阅者时,如何确保在触发事件时不会抛出exception。

// Delegate declaration public delegate void _delDisplayChange(object sender,string option); // Event declaration public event _delDisplayChange DisplayChange; //throwing the event DisplayChange(this, "DISTRIBUTION"); 

以下是推荐的方法:

 protected void RaiseDisplayChanged(string message) { var handlers = DisplayChange; if(handlers != null) handlers(this, message); } 

在检查之前复制事件处理程序枚举有两件事:

  1. 如果DisplayChange处理程序在检查和触发之间变为null,则不会死亡
  2. 如果侦听器在枚举时修改DisplayChange列表,则不会遇到奇怪的情况。

此外,您没有使用标准的事件协议。 你的代表应该是:

 public delegate void DisplayChangeDelegate(object sender, OptionsEventArgs args); 

OptionsEventArgs派生自EventArgs的位置。 更进一步,在.Net 3.5中,你永远不应该像这样定义一个委托。 相反,您应该只定义您的事件:

 public event EventHandler DisplayChanged; 

我喜欢通过定义这个类来更进一步:

 public class EventArgs : EventArgs { public T Payload { get; private set } public EventArgs(T payload) { Payload = payload; } } 

然后,您不需要定义OptionsEventArgs:

 public event EventHandler> DisplayChanged; 

只是想一些东西……

改变这个:

 // Event declaration public event _delDisplayChange DisplayChange; 

对此:

 // Event declaration public event _delDisplayChange DisplayChange = delegate{}; 

这将确保您的活动始终至少有一个订阅者。

正如Brian所说:许多消息来源建议在检查事件是否为空之前制作事件的副本:

 _delDisplayChange displayChangeCopy = DisplayChange; if (displayChangeCopy != null) displayChangeCopy(this, "DISTRIBUTION"); 

这有助于使您的代码更加线程安全,因为displayChangeCopy的值在null检查和调用之间不会改变。

继Jay的答案之后,这里有一个关于使用空委托时性能考虑因素的链接 。