C# 在引发事件之前,是否有理由将事件分配给局部变量?
我经常看到下面这样的代码,我想知道是否有任何理由为事件使用局部变量,而不仅仅是使用事件本身。有吗C# 在引发事件之前,是否有理由将事件分配给局部变量?,c#,.net,events,C#,.net,Events,我经常看到下面这样的代码,我想知道是否有任何理由为事件使用局部变量,而不仅仅是使用事件本身。有吗 var handler = OnQueryComplete; if (handler != null) handler(this, new RepositoryEventArgs<T>(results)); var handler=OnQueryComplete; if(处理程序!=null) 处理程序(这是新的RepositoryEventArgs(results)); 是的
var handler = OnQueryComplete;
if (handler != null)
handler(this, new RepositoryEventArgs<T>(results));
var handler=OnQueryComplete;
if(处理程序!=null)
处理程序(这是新的RepositoryEventArgs(results));
是的,绝对正确-它使空值检查变得安全
如果你有:
// Bad code, do not use
if (OnQueryComplete != null)
{
OnQueryComplete(this, ...);
}
然后,最后一个订户可能会在检查和调用之间取消订阅,从而导致NullReferenceException
这里有很多选择:
- 确定您不关心线程安全,即使它引发异常。(在许多情况下,这可能是合理的,特别是如果这都是您自己的代码库。)
- 使用扩展方法使这一点变得简单,以便不管怎样都可以取消空性检查
- 在C#6中,使用条件null运算符:
OnQueryComplete?.Invoke(this, ...);
- 使用一个永远不会删除的空处理程序设置事件:
public event FooEventHander OnQueryComplete = delegate {};
您可能还希望使用
Interlocked
来确保获得变量的最新值,以避免内存模型问题。有关这方面的更多讨论,请参阅。可能与@RuneFS重复:它会稍微改变它。基本上,围绕这一点总是有比赛条件的,没有完美的解决方案。谢谢你这么机敏的回答,乔恩。我刚刚习惯了委托{}
,但之前使用过您的代码示例,幸好忽略了任何线程安全性。是的,是的,它们将始终是竞争条件。最初的评论更多地是因为经常说“分配给本地”会删除竞争条件。它确实删除了一个关键的应用程序,因为应用程序可能会以其他方式崩溃,但它随后创建了另一个应用程序,在解释“分配到本地”方法时,它似乎“总是”被遗忘