是否在"null"引用(即没有订阅者的事件)上调用扩展方法?

Jud*_*ngo 59 c# events extension-methods

邪恶还是不邪恶?

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

// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);

// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);
Run Code Online (Sandbox Code Playgroud)

请注意,由于扩展方法的性质,如果MyButtonClicked为null,MyButtonClicked.Raise将不会抛出NullReferenceException.(例如,没有MyButtonClicked事件的监听器).

邪恶与否?

Dan*_*ein 35

不是邪恶的.我希望事件默认以这种方式工作.有人可以解释为什么没有订阅者的事件是空的吗?

  • 我同意没有订阅者的事件不应该为空.没有订阅者的事件是空的,这似乎相当愚蠢 - 当然他们可以用一些带有空订阅列表的可重用类来初始化它.唉,现在改变已经太晚了. (2认同)

jon*_*nii 14

您可以随时声明您的活动(不是我推荐的):

public event EventHandler<EventArgs> OnClicked = delegate { };
Run Code Online (Sandbox Code Playgroud)

这样,当你调用它们时,它们会分配给它们,所以它们不会抛出空指针异常.

您可以在C#3.0中删除委托关键字...


alv*_*vin 9

不要忘记使用[MethodImpl(MethodImplOptions.NoInlining)],否则可能是它不是线程安全的.

(很久以前就读过那个地方,记得它,谷歌搜索并发现http://blog.quantumbitdesigns.com/tag/events/)


Squ*_*rel 6

来自java背景,这对我来说似乎总是很奇怪.我认为没有人听一个事件是完全有效的.特别是在动态添加和删除侦听器时.

对我来说,这似乎是C#的gottchas之一,当人们不知道/忘记每次检查null时会导致错误.

隐藏此实现细节似乎是一个很好的计划,因为它无助于每次检查空值的可读性.我确信如果没有人在监听,MSFT会说没有构建事件会有性能提升,但是在大多数业务代码中,无意义的空指针异常/可读性的降低远远超过了它.

我还将这两个方法添加到类中:

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

    public static void Raise<TA>(this EventHandler<TA> handler, object sender, TA args)
        where TA : EventArgs
    {
        if (handler != null)
        {
            handler(sender, args);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 5

为什么会是邪恶的?

它的目的很明确:它引发了MyButtonClicked事件.

它确实增加了一个函数调用开销,但是在.NET中,无论如何它都会被优化掉或非常快.

这有点微不足道,但它解决了我对C#的最大抱怨.

总的来说,我认为这是一个奇妙的想法,并可能会偷走它.