事件处理程序提升方法约定

Nei*_*ell 6 c# delegates coding-style

我只是在浏览并遇到了这个问题:

行动与委托事件

来自nobug的答案包括以下代码:

protected virtual void OnLeave(EmployeeEventArgs e) {
  var handler = Leave;
  if (handler != null)
    handler(this, e);
}
Run Code Online (Sandbox Code Playgroud)

使用"创建提升方法"快速修复时,Resharper也会生成类似的代码.

我的问题是,为什么这条线是必要的?:

var handler = Leave;
Run Code Online (Sandbox Code Playgroud)

为什么写这个更好?:

protected virtual void OnLeave(EmployeeEventArgs e) {
  if (Leave != null)
    Leave(this, e);
}
Run Code Online (Sandbox Code Playgroud)

Fre*_*örk 12

它更好,因为Leave在null检查之后但在调用之前(这会导致代码抛出a NullReferenceException)之前,有一个很小的可能性变为null .由于委托类型是不可变的,如果你首先将它分配给变量,这种可能性就会消失; Leave转让后,您的本地副本不会受到任何更改的影响.

请注意,这种方法也会产生相反的问题; 它意味着事件处理程序在从事件中分离后会被调用(微小但存在).当然也应该优雅地处理这种情况.


Aar*_*els 5

在多线程应用程序中,如果调用者从事件中取消注册,则可能会获得空引用异常.对局部变量的赋值可以防止这种情况发生.

可能你永远不会看到这种情况(直到它伤到你最坏的情况).这是一种看待它的方式,显示问题......

protected virtual void OnLeave(EmployeeEventArgs e) {
  if (Leave != null) //subscriber is registered to the event
  {
    //Subscriber unregisters from event....
    Leave(this, e); //NullReferenceException!
  }
}
Run Code Online (Sandbox Code Playgroud)