Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.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#_.net_Events - Fatal编程技术网

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重复:它会稍微改变它。基本上,围绕这一点总是有比赛条件的,没有完美的解决方案。谢谢你这么机敏的回答,乔恩。我刚刚习惯了
委托{}
,但之前使用过您的代码示例,幸好忽略了任何线程安全性。是的,是的,它们将始终是竞争条件。最初的评论更多地是因为经常说“分配给本地”会删除竞争条件。它确实删除了一个关键的应用程序,因为应用程序可能会以其他方式崩溃,但它随后创建了另一个应用程序,在解释“分配到本地”方法时,它似乎“总是”被遗忘