繁体   English   中英

在C#中提升事件:表现和优雅

[英]Raising Events in C#: performance and elegance

习惯于VB.NET,我习惯于“只是举起事件”。 当然,自定义事件有所不同,但有“常规”事件 - 我不需要在提升之前检查代表是否为Nothing

使用C#,我发现自己重复这种模式:

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

我以为以下模式可能会更优雅:

  1. myHandler初始化为空lambda: myHandler = (sender, e) => { };
  2. myHandler预计永远不会为null,所以提升只会变成: myHandler(this, new EventArgs());

这种模式会比前一种模式更多或更少吗? 我还应该考虑其他重要因素吗?

这在建筑中是额外的事情,但它不会是巨大的开销。 需要注意的一点是,某些序列化框架(如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

通常的做法是使用受保护的虚方法OnEventName,您可以在其中检查事件是否为null并将其提升:

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

这允许您将所有事件引发代码放在一个位置(无空检查重复),并在以后根据需要覆盖它。 因此,对于每个事件添加一个虚拟事件处理程序而不是每个事件进行一次空检查,我看不出任何好处。

BTW更短的添加虚处理程序的方法是myHandler = delegate {};

不要认为提供的第一和第二种情况之间存在显着差异,至少不要考虑它们。 过于频繁地使用委托,缺少if (myHandler != null)顺便说一句,可以带来一些性能上的好处。 因此,如果您确定处理程序永远不会为 null ,那么摆脱控制权基本上就完成了。

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

在谈论优雅时 ,应该指出VB.NET中的RaiseEvent关键字会被编译器自动扩展为完全相同的构造,您必须在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中使用的样式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM