如何安全地发射事件
当事件没有订阅者时,如何确保在触发事件时不会抛出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); }
在检查之前复制事件处理程序枚举有两件事:
- 如果DisplayChange处理程序在检查和触发之间变为null,则不会死亡
- 如果侦听器在枚举时修改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的答案之后,这里有一个关于使用空委托时性能考虑因素的链接 。