哪个是调用事件委托的更好方法?

时间:2013-02-22 08:21:58

标签: c# events event-handling

private void NotifyFreeChannelsChanged() //1.
{
    if (FreeChannelsChanged != null)
    {
        FreeChannelsChanged(this, null);
    }
}

private void NotifyFreeChannelsChanged() //2.
{
    NotifyCollectionChangedEventHandler h = FreeChannelsChanged ;
     if (h != null)
         h(this, e);
}

这些更好,为什么。或者它只是一个额外的检查。不是一个主要的区别。

3 个答案:

答案 0 :(得分:6)

“更好的”?好吧,不包含(特定的)竞争条件,一个。 MultiCastDelegate类型是不可变的,并且在所有重要的方式中使用值类型语义(但 引用类型,请参阅this,更重要的是,this),这就是为什么先分配然后再检查。问题是:

// this evaluates to true...
if(SomeEvent != null)
{
    // ...but before this line executes, the last 
    // subscriber detached, and now SomeEvent is null. Oops.
    SomeEvent(this, e);
}

您应该问“为什么有人会使用示例#2?”


顺便说一句,这是一个使用隐式类型变量(var)的好地方。那些委托类型名称变长......

同样有趣的是,竞争条件仍然存在,它更加微妙。如果订户在转让后被删除会怎样?嗯,它仍会被调用,但实际上没有(我知道)你能做到的。

答案 1 :(得分:1)

第二个很容易适用于我们使用的一组扩展方法,其中EventHandler是方法的目标。

public static void Raise(this EventHandler handler, object sender)
{
  if (handler != null)
    handler(sender, EventArgs.Empty);
}

// And then...
TheEvent.Raise(this);

据我所知,您将处理程序传递给方法的事实为您提供了本地副本以避免竞争条件。

答案 2 :(得分:0)

第二个是防止可能的线程错误,其中在空检查和片段1中的事件触发之间发生上下文切换。其他一些线程可以将它设置为空。

因此,除非您的方法容易出现多线程,否则您可以使用更简单的代码段。