事件处理程序提升方法约定
我只是在浏览并遇到了这个问题:
行动与委托事件
来自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); }
它更好,因为在null检查之后,但在调用之前, Leave
变为null的可能性很小(这会导致代码抛出NullReferenceException
)。 由于委托类型是不可变的,如果你首先将它分配给变量,这种可能性就会消失; 转让后Leave
的任何更改都不会影响您的本地副本。
请注意,这种方法也会产生相反的问题; 它意味着事件处理程序在从事件中分离后会调用(微小但存在)的可能性。 当然也应该优雅地处理这种情况。
在multithreading应用程序中,如果调用者从事件中取消注册,则可能会获得空引用exception。 对局部变量的赋值可以防止这种情况发生。
赔率是你永远不会看到这一点(直到它伤害你最坏的情况)。 这是一种看待它的方式,显示问题……
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的一个很好的解释:
赛事和比赛