是调用一个“空”参考(即没有用户事件)的扩展方法邪恶?
邪恶还是不邪恶?
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 { };
这样,当你调用它们时,他们有一些东西被分配给它们,所以它们不会抛出空指针exception。
你可能会摆脱C#3.0中的委托关键字…
不要忘记使用[MethodImpl(MethodImplOptions.NoInlining)]
,否则它可能不是线程安全的。
(很久以前就读过,想起来,用googlesearch,发现http://blog.quantumbitdesigns.com/tag/events/ )
从java背景来看,这对我来说总是很古怪。 我认为没有人听一个事件是完全有效的。 尤其是当侦听器被dynamic添加和删除时。
对我来说,这似乎是C#的gottchas之一,当人们不知道/忘记每次检查空值时会导致错误。
隐藏这个实现细节似乎是一个很好的计划,因为它不会帮助每一次检查空值的可读性。 我确信MSFT会说如果没有人在监听,那么在没有构build事件的情况下性能会有所提高,但是在大多数业务代码中,无用的空指针exception/可读性下降会大大超过它。
我也将这两个方法添加到类中:
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){ }
模式以及它如何通过inheritance来处理可扩展性。 它是否假定所有的子类都会处理这个事件,而不是重写一个方法?
虽然我不会把它形容为邪恶的 ,但它仍然有一个负面的含义,因为它增加了不必要的开销:
打电话时
myEvent.Raise(this, new EventArgs());
对象EventArgs在所有情况下都被初始化,即使没有人订阅myEvent。
使用时
if (myEvent!= null) { myEvent(this, new EventArgs()); }
EventArgs只有在订阅了myEvent的情况下才被初始化。
在没有处理程序的情况下抛出exception是最不可取的。 如果没有处理程序,最好是空的而不是空的。