代码之家  ›  专栏  ›  技术社区  ›  Judah Gabriel Himango

是否对“空”引用(即没有订阅服务器的事件)调用扩展方法是错误的?

  •  59
  • Judah Gabriel Himango  · 技术社区  · 16 年前

    邪恶与否?

    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为空,则MyButtonClicked.Rise不会引发NullReferenceException。(例如,MyButtonClicked事件没有侦听器)。

    邪恶与否?

    8 回复  |  直到 10 年前
        1
  •  35
  •   Dan Goldstein    16 年前

    不是邪恶。我希望事件在默认情况下以这种方式进行。有人能解释为什么没有订户的事件是空的吗?

        2
  •  14
  •   jonnii    16 年前

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

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

    这样,当您调用它们时,它们就有了分配给它们的东西,因此它们不会抛出空指针异常。

    您可能可以去掉C 3.0中的delegate关键字…

        3
  •  9
  •   alvin    16 年前

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

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

        4
  •  6
  •   community wiki Squirrel    16 年前

    从Java背景来看,这对我来说总是很奇怪。我认为没有人听一个事件是完全正确的。特别是当动态添加和删除监听器时。

    对我来说,这似乎是一个C的Gottchas,当人们不知道/忘记每次检查空值时,它会导致错误。

    隐藏这个实现细节似乎是一个很好的计划,因为它并不能帮助可读性来检查每一次的空值。我相信MSFTS会说,如果没有人在监听,那么在不构造事件的过程中会有一个性能的提高,但是imho它被大多数业务代码中无意义的空指针异常/可读性的降低大大超过。

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

        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);
            }
        }
    
        5
  •  5
  •   David    16 年前

    为什么会是邪恶的?

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

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

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

    总的来说,我认为这是一个很好的主意,很可能会被偷走。

        6
  •  0
  •   Greg D    16 年前

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

    protected virtual OnSomeEvent(EventArgs e){ }
    

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

        7
  •  0
  •   Bob    14 年前

    尽管我不认为它是 邪恶的 它仍然具有负面影响,因为它增加了不必要的开销:

    打电话时

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

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

    使用时

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

    只有当有人订阅MyEvent时,EventArgs才会初始化。

        8
  •  -2
  •   Prakash    13 年前

    在没有处理程序的情况下抛出异常并不是最可取的。如果没有处理程序,最好是空的,而不是空的。