在“ null”上调用扩展方法引用(即没有订阅者的事件)邪恶?

StackOverflow https://stackoverflow.com/questions/248072

  •  05-07-2019
  •  | 
  •  

邪恶与否?

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);

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

邪恶与否?

有帮助吗?

解决方案

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

其他提示

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

public event EventHandler<EventArgs> OnClicked = delegate { };

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

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

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

(在很久以前的某个地方读过,记得它,谷歌搜索并找到 http://blog.quantumbitdesigns。 com / tag / events /

来自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);
        }
    }

为什么会是邪恶的?

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

它确实增加了一个函数调用开销,但是在.NET中它将被优化掉或者相当快。

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

总的来说,我认为这是一个很棒的主意,并且很可能会偷走它。

我不会说这是邪恶的,但我对你的扩展方法如何适应

感兴趣
protected virtual OnSomeEvent(EventArgs e){ }

模式以及它如何通过继承处理可扩展性。是否假定所有子类都将处理事件而不是覆盖方法?

虽然我不会将其描述为 evil ,但它仍然具有负面含义,因为它会增加不必要的开销:

致电

myEvent.Raise(this,new EventArgs());

对象EventArgs在所有情况下都被初始化,即使没有人订阅myEvent。

使用时

if (myEvent!= null) {
   myEvent(this, new EventArgs());
}

仅当有人订阅了myEvent时才会初始化EventArgs。

当没有处理程序时抛出异常并不是最好的。如果它没有处理程序,最好是空而不是null。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top