views:

4150

answers:

8

It is not possible to fire an event in C# that has no handlers attached to it. So before each call it is necessary to check if the event is null.

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

I would like to keep my code as clean as possible and get rid of those null checks. I don't think it will affect performance very much, at least not in my case.

MyEvent( param1, param2 );

Right now I solve this by adding an empty inline handler to each event manually. This is error prone, since I need to remember to do that etc.

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

Is there a way to generate empty handlers for all events of a given class automatically using reflection and some CLR magic?

+31  A: 

I saw this on another post and have shamelessly stolen it and used it in much of my code ever since:

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) // Unnessecary!
        Click(this, "foo");
}

* If anyone knows the origin of this technique, please post it in the comments. I really do believe in the source getting due credit.

(Edit: I got it from this post http://stackoverflow.com/questions/9033/hidden-features-of-c#9282)

Dinah
24 seconds faster!
leppie
Add empty delegate, right there! That's even better than I was hoping for. Thanks! I'm going to read the "hidden features" post right now.
TomA
Yes -- That post is priceless! Be sure to vote often there. They've done us all a great service.
Dinah
lol. I think i just cut about 300 lines from my codebase!
Stimul8d
+3  A: 

You can write is as:

MyEvent += delegate { };

I am not sure what you want to do is correct.

leppie
TcKs
A: 

Original post is here

Android
+13  A: 

The notation:

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

is not thread safe. You should do it this way:

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

I understand, that this is a bother, so you can do helper method:

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

and then call:

RaiseEvent( MyEvent, param1, param2 );

If you are using C# 3.0, you can declare helper method as extension method:

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

and then call:

MyEvent.Raise( param1, param2 );

Also you can create next extension/helper methods for other event handlers. For example:

static void Raise<TEventArgs>( this EventhHandler<TEventArgs> handler,
    object sender, TEventArgs e ) where TEventArgs : EventArgs
{
    if ( null != handler ) { handler( sender, e ); }
}
TcKs
Using an extension method is a beautiful solution. I cringe when the notion of initializing an empty delegate is put forth.
Greg
Wow, I thought the `= delegate {}` was handy when I saw it for the first time. This is +1 awesome, though. And so obvious with hindsight, dammit :)
shambulator
+2  A: 

This is a bad idea in that the code which is consuming the event now has an expectation that the object with the event has been coded with an action by default. If your code is never going to be used anywhere else by anyone else then I guess you can get away with it.

mcintyre321
I agree, as I commented on leppie's answer.+1
TcKs
+1  A: 

You don't need several extension methods for different event handlers, you just need one:

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);
  }
}
vkelman
A: 

the trick in the accepted answer will avoid having to check for null but will not ensure thread safty. see here: http://stackoverflow.com/questions/1131184/c-initializing-an-event-handler-with-a-dummy/1131204#1131204

NullReferenceException
A: 

You can use PostSharp to on build time add this magic. It is the best way.

Jairo