C# 事件处理程序引发方法约定
我只是浏览一下,发现了这个问题: 包括以下代码:C# 事件处理程序引发方法约定,c#,coding-style,delegates,C#,Coding Style,Delegates,我只是浏览一下,发现了这个问题: 包括以下代码: protected virtual void OnLeave(EmployeeEventArgs e) { var handler = Leave; if (handler != null) handler(this, e); } 当使用“创建提升方法”快速修复时,Resharper也会生成类似的代码 我的问题是,为什么这条线是必要的 var handler = Leave; 为什么它比写这个好 protected virt
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null)
handler(this, e);
}
当使用“创建提升方法”快速修复时,Resharper也会生成类似的代码
我的问题是,为什么这条线是必要的
var handler = Leave;
为什么它比写这个好
protected virtual void OnLeave(EmployeeEventArgs e) {
if (Leave != null)
Leave(this, e);
}
这更好,因为在null检查之后,调用之前,
Leave
很可能会变为null(这会导致代码抛出NullReferenceException
)。由于委托类型是不可变的,如果您首先将其分配给变量,这种可能性就会消失;派遣后,休假
的任何更改都不会影响您的本地副本
但请注意,这种方法也会产生相反的问题;这意味着事件处理程序在与事件分离后被调用的可能性(很小,但已经存在)。当然,这种情况也应该妥善处理。在多线程应用程序中,如果调用方从事件中注销,则可能会出现空引用异常。对局部变量的赋值可以防止这种情况 很可能你永远不会看到这一点(直到它伤害你最深)。这里有一种方法可以说明问题所在
protected virtual void OnLeave(EmployeeEventArgs e) {
if (Leave != null) //subscriber is registered to the event
{
//Subscriber unregisters from event....
Leave(this, e); //NullReferenceException!
}
}
以下是Eric Lippert的精彩解释:
是的。取消注册后调用事件处理程序是一场不可调整的竞赛。NRE很容易修复。