59

恶还是不恶?

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 事件的侦听器)。

恶不恶?

4

8 回答 8

35

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

于 2008-10-29T19:24:28.663 回答
14

你总是可以这样声明你的事件(不是我推荐的):

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

这样,当您调用它们时,它们就会分配给它们,因此它们不会引发空指针异常。

您可能可以摆脱 C# 3.0 中的委托关键字...

于 2008-10-29T19:29:18.293 回答
9

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

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

于 2008-11-16T03:19:44.273 回答
6

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

对我来说,这似乎是 C# 的问题之一,当人们不知道/忘记每次都检查 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);
        }
    }
于 2008-11-11T11:48:40.947 回答
5

为什么会是邪恶的?

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

它确实增加了函数调用开销,但在 .NET 中,它要么被优化掉,要么非常快。

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

总的来说,我认为这是一个绝妙的主意,并且可能会窃取它。

于 2008-10-29T19:27:02.993 回答
0

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

protected virtual OnSomeEvent(EventArgs e){ }

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

于 2008-10-29T19:32:22.953 回答
0

尽管我不会将其描述为evil,但它仍然具有负面影响,因为它增加了不必要的开销:

打电话时

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

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

使用时

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

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

于 2010-02-18T11:04:27.433 回答
-2

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

于 2011-09-07T07:24:05.227 回答