在代码审查中,我偶然发现了这个(简化的)代码片段以注销事件处理程序:
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
是必需的。