当前位置:  开发笔记 > 编程语言 > 正文

自动创建空的C#事件处理程序

如何解决《自动创建空的C#事件处理程序》经验,为你挑选了5个好方法。

无法在没有附加处理程序的C#中触发事件.因此,在每次调用之前,有必要检查事件是否为空.

if ( MyEvent != null ) {
  MyEvent( param1, param2 );
}

我想保持我的代码尽可能干净,并摆脱那些空检查.我不认为这会影响性能,至少在我的情况下不会.

MyEvent( param1, param2 );

现在我通过手动为每个事件添加一个空的内联处理程序来解决这个问题.这很容易出错,因为我需要记住这样做等等.

void Initialize() {
  MyEvent += new MyEvent( (p1,p2) => { } );
}

有没有办法使用反射和一些CLR魔法自动为给定类的所有事件生成空处理程序?



1> Dinah..:

我在另一个帖子上看到了这个并且无耻地偷了它并且在我的大部分代码中使用它从那以后:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

//Let you do this:
public void DoSomething() {
    Click(this, "foo");
}

//Instead of this:
public void DoSomething() {
    if (Click != null) // Unnecessary!
        Click(this, "foo");
}

*如果有人知道这种技术的起源,请在评论中发布.我确实相信来源得到应有的信任.

(编辑:我从这个帖子中获得了C#的隐藏功能?)


-1有两个原因:1)这种技术会产生运行时性能和内存开销; 2)这种技术容易出错,特别是与下面描述的扩展方法相比.单独查看调用站点不足以确定此方法的正确性,但扩展方法适用于所有事件,无论事件是否使用空委托进行初始化.
添加空委托,就在那里!这甚至比我希望的更好.谢谢!我现在要阅读"隐藏的功能"帖子.
大声笑.我想我只是从我的代码库中删除了大约300行!

2> TcKs..:

符号:

if ( MyEvent != null ) {
  MyEvent( param1, param2 );
}

不是线程安全的.你应该这样做:

EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }

我明白,这是一个麻烦,所以你可以做帮助方法:

static void RaiseEvent( EventHandler handler, object sender, EventArgs e ) {
    if ( null != handler ) { handler( sender, e ); }
}

然后打电话:

RaiseEvent( MyEvent, param1, param2 );

如果您使用的是C#3.0,则可以将helper方法声明为扩展方法:

static void Raise( this EventHandler handler, object sender, EventArgs e ) {
    if ( null != handler ) { handler( sender, e ); }
}

然后打电话:

MyEvent.Raise( param1, param2 );

您还可以为其他事件处理程序创建下一个扩展/帮助程序方法.例如:

static void Raise( this EventHandler handler,
    object sender, TEventArgs e ) where TEventArgs : EventArgs
{
    if ( null != handler ) { handler( sender, e ); }
}


使用扩展方法是一个很好的解决方案.当提出初始化空代表的概念时,我感到畏缩.

3> gandaliter..:

在C#6.0中,由于有条件的null运算符,因此无需使用任何这些长度来执行null检查 ?.

该文档解释说,调用MyEvent?.Invoke(...)会将事件复制到一个临时变量,执行null检查,如果不为null,则调用Invoke该临时副本。从某种意义上说,这不一定是线程安全的,因为有人可以在将副本复制到临时变量之后添加一个新事件,该事件不会被调用。它确实保证您不会调用Invokenull。

简而言之:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click;

public void DoSomething() {
    Click?.Invoke(this, "foo");
}



4> leppie..:

你可以这样写:

MyEvent += delegate { };

我不确定你想做什么是正确的.



5> vkelman..:

对于不同的事件处理程序,您不需要多种扩展方法,只需要一个:

public static class EventHandlerExtensions {
  public static void Raise(this EventHandler handler, object sender, T args) where T : EventArgs {
    if (handler != null) handler(sender, args);
  }
}

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有