2012-03-19 111 views
4

习惯了VB.NET,我习惯于“只是引发事件”。当然,自定义事件有所不同,但对于“常规”事件 - 我不需要在筹集之前检查代表是否为Nothing用C#举办活动:性能和优雅

在C#中,我发现自己重复这种模式:

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

我在想,下面的模式可能被证明更优雅:myHandler = (sender, e) => { };

  1. 将myHandler与空拉姆达初始化
  2. myHandler预计永远不会为空,因此提高会变成:myHandler(this, new EventArgs());

这个模式会比上一个更好或更差吗? 我应该考虑其他重要考虑因素吗?

+2

查看回答这个非常类似的问题:http://stackoverflow.com/questions/170907/is-there-a-downside-to-adding-an-anonymous-empty-delegate-on-event-declaration – 2012-03-19 07:47:18

+0

错过了那个,thanx! – 2012-03-19 08:04:58

回答

1

我认为这两种方法之间的性能差异不够大是相关的。如果有的话,我会争辩说,即使它是无操作的,通过代理调用方法,空检查是更便宜

在谈到优雅,应该指出的是,在VB.NET is automatically expanded by the compilerRaiseEvent关键字精确,你必须自己写在C#中同一构造:

If (Not MyEvent Is Nothing) Then 
    MyEvent.Invoke(New EventArgs()) 
End If 

如果你想避免

public static void RaiseEvent(this EventHandler source, object sender) 
{ 
    if (source != null) 
    { 
     source.Invoke(sender, new EventArgs()); 
    } 
} 

public static void RaiseEvent<T>(this EventHandler<T> source, object sender, T eventArgs) 
    where T : EventArgs 
{ 
    if (source != null) 
    { 
     source.Invoke(sender, eventArgs); 
    } 
} 

这样,你可以简单地说:重复整个代码结构,你可以在一对夫妇的扩展方法将其封装

myEvent.RaiseEvent(this); 
myOtherEvent.RaiseEvent(this, new SomeEventArgs()); 

它在语义上等同于VB.NET中使用的风格。

1

不要认为提供的第一和第二种情况之间存在显着差异,至少没有太多考虑它们。 太频繁使用代表缺乏if (myHandler != null)可能,顺便说一句,你有一些性能好处。所以如果你确定处理器是从来没有null,摆脱这种控制,基本上你做了。

5

这是在施工中发生的额外事情,但它不会是巨大的开销。有一点需要注意,像DataContractSerializer(WCF)这样的一些序列化框架不会运行构造函数或字段初始值设定项,所以它可能不是非null。就个人而言,如果你的大多数事件都EventHandler,我可能会尝试使用扩展方法:

public static void SafeInvoke(this EventHandler handler, object sender) { 
    if (handler != null) handler(sender, EventArgs.Empty); 
} 

则:

SomeEvent.SafeInvoke(this); 

但坦率地说,我很少有一个问题,只需使用null-check; p

另一个缺点是,如果您有足够的事件发生此问题,则应该使用EventHandlerList代替 - 而且此方法不适用于EventHandlerList

2

常见的做法是使用受保护的虚拟方法的OnEventName在那里你可以检查,如果事件为null,提高它:

protected virtual void OnEventName(parameters) 
{ 
    if (EventName != null) 
     EventName(this, new EventNameEventArgs(parameters); 
} 

这可以让你在一个地方的所有事件,提高代码(没有空检查重复),如果需要,稍后覆盖它。所以我没有看到为每个事件添加一个虚拟事件处理程序而不是每个事件有一个空检查的好处。

BTW短的方式来增加虚拟处理器是myHandler = delegate {};