【发布时间】:2010-09-22 12:16:30
【问题描述】:
在一次代码审查中,我偶然发现了这个(简化的)代码片段来取消注册事件处理程序:
Fire -= new MyDelegate(OnFire);
我认为这不会取消注册事件处理程序,因为它会创建一个以前从未注册过的新委托。但是搜索 MSDN 我发现了几个使用这个成语的代码示例。
于是我开始了一个实验:
internal class Program
{
public delegate void MyDelegate(string msg);
public static event MyDelegate Fire;
private static void Main(string[] args)
{
Fire += new MyDelegate(OnFire);
Fire += new MyDelegate(OnFire);
Fire("Hello 1");
Fire -= new MyDelegate(OnFire);
Fire("Hello 2");
Fire -= new MyDelegate(OnFire);
Fire("Hello 3");
}
private static void OnFire(string msg)
{
Console.WriteLine("OnFire: {0}", msg);
}
}
令我惊讶的是,发生了以下事情:
-
正如预期的那样,
Fire("Hello 1");产生了两条消息。 -
Fire("Hello 2");产生了一条消息!
这让我确信取消注册new代表是可行的! -
Fire("Hello 3");扔了一个NullReferenceException。
调试代码显示注销事件后Fire为null。
我知道对于事件处理程序和委托,编译器会在后台生成大量代码。但是我还是不明白为什么我的推理是错误的。
我错过了什么?
附加问题:根据Fire 是null 的事实,当没有注册事件时,我得出结论,无论何时触发事件,都需要检查null。
【问题讨论】: