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

时间:2010-02-17 17:24:07

标签: c# coding-style delegates

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

Action vs delegate event

The answer from nobug包含此代码:

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);
}

3 个答案:

答案 0 :(得分:12)

这样做更好,因为Leave在空检查之后但在调用之前变为空的可能性很小(这会导致代码抛出NullReferenceException)。由于委托类型是不可变的,如果你首先将它分配给变量,这种可能性就会消失;分配后{1 {}}的任何更改都不会影响您的本地副本。

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

答案 1 :(得分:5)

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

你可能永远不会看到这种情况(直到它伤到你最坏的情况)。以下是一种查看问题的方法......

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

答案 2 :(得分:1)

以下是Eric Lippert的一个很好的解释:

Events and races