Share via


Safely firing an event, Part 2

A while back I wrote about Safely firing an event.

 

I come to you now with another solution to the problem, which I like quite a bit more.

 

In Properties with events: another attempt, we tried initializing an event with an empty anonymous method. It works, but there’s always a risk that one of your constructors won’t do the right thing.

 

It turns out that you can use a field initializer on an event. I don’t know why I didn’t try this yesterday, its seems obvious now!

 

            public event System.EventHandler MyEvent = delegate { };

 

                  c.MyEvent(this, EventArgs.Empty); // no null check required!

Voila! The event will never be null.

 

There may be a small perf hit, but until my perf analysis tells me that this specific instance is a perf problem, I’m fine as-is.

 

If your class wants to check if there are any listeners, it can no longer do:

 

                  if (c.MyEvent == null)

                  {

                        // no one listens to me.

                  }

 

Instead you’d have to do:

 

                  // 1 because it always contains the empty delegate

                  if (c.MyEvent.GetInvocationList().Length == 1)

                  {

                        // no one listens to me.

                  }

 

If I am ever inclined to write such code, I will first think about changing my design so the problem goes away, and second do some Extract Method Refactorings to hide the nasty bits.

Comments

  • Anonymous
    June 17, 2004
    why would i ever use method 2 over testing for null?

    method 1 does one simple test... whereas method 2 has to call a virtual method to retrieve an array which has to provide the length of invokers and what not...

    seriously man, why would you EVER favor method2 over simply checking for null???
  • Anonymous
    June 17, 2004
    The comment has been removed
  • Anonymous
    June 17, 2004
    This is an implementation of the NullObject pattern, which has some applicability in some situations, but admittedly not all. Checking for null is very action orientated when really the <b>intention</b> of the eventing class is to simply tell listening observers about a particular event. O-O in general has it's costs, in C# just as much as any language, especially with the dynamic dispatch. PErsonally, I do do a check for null. If you want to make the code more intention revealing I'd proabbly do a extract method refactoring or introduce explaining variable:

    ...
    bool thereArePriceUpdateListeners = (PriceUpdate != null ) ;

    if ( thereArePriceUpdateListeners ) {
    OnPriceUpdate(...) ;

    This makes the code more readable, the intentions are clear and no dynmaic dispatch costs.

    An alternative pattern is to use the State pattern to achieve the same goal.
  • Anonymous
    June 17, 2004
    Simpler, so better.

    I was talking with someone about C#'s baked in robustness last night. This is one area where they missed the boat.

    Like you, I would gladly take robustness over "potential" performance issues. Now if only I could do this in my code today!
  • Anonymous
    June 18, 2004
    I agree with the other comments, the null check for events should be built into the Framework. However, this is a nice workaround. Too bad it has to wait for VS2005 in order to do this "cleanly".
  • Anonymous
    June 29, 2004
    The comment has been removed
  • Anonymous
    June 30, 2004
    Udo: You'll need Whidbey (VS 2005) to do this.

    Try it out:

    http://blogs.msdn.com/jaybaz_ms/archive/2004/06/29/168872.aspx
  • Anonymous
    March 21, 2006
    PingBack from http://www.conchoid.com/2006/03/21/dealing-with-lazy-design-habits/