Tom*_*rle 68 c# clr events delegates
无法在没有附加处理程序的C#中触发事件.因此,在每次调用之前,有必要检查事件是否为空.
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
Run Code Online (Sandbox Code Playgroud)
我想保持我的代码尽可能干净,并摆脱那些空检查.我不认为这会影响性能,至少在我的情况下不会.
MyEvent( param1, param2 );
Run Code Online (Sandbox Code Playgroud)
现在我通过手动为每个事件添加一个空的内联处理程序来解决这个问题.这很容易出错,因为我需要记住这样做等等.
void Initialize() {
MyEvent += new MyEvent( (p1,p2) => { } );
}
Run Code Online (Sandbox Code Playgroud)
有没有办法使用反射和一些CLR魔法自动为给定类的所有事件生成空处理程序?
Din*_*nah 145
我在另一个帖子上看到了这个并且无耻地偷了它并且在我的大部分代码中使用它从那以后:
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");
}
Run Code Online (Sandbox Code Playgroud)
*如果有人知道这种技术的起源,请在评论中发布.我确实相信来源得到应有的信任.
(编辑:我从这个帖子中获得了C#的隐藏功能?)
TcK*_*cKs 58
符号:
if ( MyEvent != null ) {
MyEvent( param1, param2 );
}
Run Code Online (Sandbox Code Playgroud)
不是线程安全的.你应该这样做:
EventHandler handler = this.MyEvent;
if ( null != handler ) { handler( param1, param2 ); }
Run Code Online (Sandbox Code Playgroud)
我明白,这是一个麻烦,所以你可以做帮助方法:
static void RaiseEvent( EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
Run Code Online (Sandbox Code Playgroud)
然后打电话:
RaiseEvent( MyEvent, param1, param2 );
Run Code Online (Sandbox Code Playgroud)
如果您使用的是C#3.0,则可以将helper方法声明为扩展方法:
static void Raise( this EventHandler handler, object sender, EventArgs e ) {
if ( null != handler ) { handler( sender, e ); }
}
Run Code Online (Sandbox Code Playgroud)
然后打电话:
MyEvent.Raise( param1, param2 );
Run Code Online (Sandbox Code Playgroud)
您还可以为其他事件处理程序创建下一个扩展/帮助程序方法.例如:
static void Raise<TEventArgs>( this EventHandler<TEventArgs> handler,
object sender, TEventArgs e ) where TEventArgs : EventArgs
{
if ( null != handler ) { handler( sender, e ); }
}
Run Code Online (Sandbox Code Playgroud)
在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");
}
Run Code Online (Sandbox Code Playgroud)
对于不同的事件处理程序,您不需要多种扩展方法,只需要一个:
public static class EventHandlerExtensions {
public static void Raise<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs {
if (handler != null) handler(sender, args);
}
}
Run Code Online (Sandbox Code Playgroud)