Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 事件处理程序引发方法约定_C#_Coding Style_Delegates - Fatal编程技术网

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很容易修复。