【问题标题】:Checking if the handler != null vs Checking if the event != null in C# [duplicate]检查处理程序是否!= null vs 检查事件是否!= C#中的 null [重复]
【发布时间】:2013-08-04 07:47:09
【问题描述】:

我已经看到了在 C# 中触发事件的各种编码风格。 第一个样式包含以下内容:

-事件处理程序

    public delegate void NumberReachedEventHandler(object sender, 
    NumberReachedEventArgs e);

-一个事件

    public event NumberReachedEventHandler NumberReached;

-以及触发事件的方法

    protected virtual void OnNumberReached(NumberReachedEventArgs e)
    {
        if(NumberReached != null)
        {
            NumberReached(this, e);
        }
    }

然而,第二种样式有不同的触发事件的方法:

    protected virtual void OnNumberReached(NumberReachedEventArgs e)
    {
        NumberReachedEventHandler handler = NumberReached;
        if(handler != null)
        {
            handler(this, e);
        }
    }

在我看来,一种样式检查“事件”是否为空,而第二种样式检查委托是否为空。但是,我的理解是事件只是委托的一个实例,所以我想知道这两种编写代码的方式是否有任何优势。如果是这样,请解释一下。提前致谢。

【问题讨论】:

    标签: c# events delegates null handler


    【解决方案1】:

    两者都在检查与事件关联的委托是否为空。

    存储到本地的目的是防止多线程代码中出现TOCTOU 风格的竞争。

    请务必注意,使用本地人只会消除两种潜在种族中的一种。有关详细信息,请参阅我 2009 年有关该主题的文章:http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx

    还有这个问题:

    C# Events and Thread Safety

    【讨论】:

      【解决方案2】:

      根据我对this 答案的理解,第一个不是线程安全的,而第二个是。

      protected virtual void OnNumberReached(NumberReachedEventArgs e)
      {
          //If number reached is changed from after this check
          if(NumberReached != null)
          {
              //and between this call, it could still result in a
              //NullReferenceException
              NumberReached(this, e);
          }
      }
      

      【讨论】:

      • 重要的是要注意,这只会消除两种可能的竞争条件之一。虽然这不会取消对 null 的引用,但事件处理程序仍然可以在 取消订阅后调用,这是一场竞赛。
      猜你喜欢
      • 2017-04-21
      • 2014-03-24
      • 2011-01-31
      • 2010-12-19
      • 2011-08-12
      • 2021-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多