在一次代码审查中,我偶然发现了这个(简化的)代码片段来注销一个事件处理程序:
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");
生成了两条消息,而expected.Fire("Hello 2");
生成了一条消息!这让我确信,注销works!
Fire("Hello 3");
的new
委托抛出了一个NullReferenceException
。调试代码显示,注销事件后Fire
为null
。
我知道对于事件处理程序和委托,编译器会在后台生成大量代码。但我还是不明白为什么我的推理是错的。
我遗漏了什么?
附加问题:根据没有注册事件时Fire
为null
的事实,我得出结论,无论在哪里触发事件,都需要对null
进行检查。
https://stackoverflow.com/questions/292820
复制相似问题