tags:

views:

68

answers:

5

I'm making custom events for C# and sometimes it isn't working.

This is how I'm making the event happen:

    private bool isDoorOpen;
    public bool IsDoorOpen {
        get { return isDoorOpen;}
        private set { isDoorOpen = value; DoorsChangeState(this, null);}
    }

And these are the event declarations:

    //events        
    public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
    public event ChangedEventHandler PositionChanged;
    public event ChangedEventHandler DirectionChanged;
    public event ChangedEventHandler BreaksChangeState;
    public event ChangedEventHandler DoorsChangeState;

This works as long as there are methods attached to the events, but if there isn't, it throws a null ref exception. What am I doing wrong?

A: 

If a event isn't subscribed to when it fires, a NullReferenceException will be thrown. This is correct behaviour, not something you've done wrong.

You should check:

if(DoorsChangeState != null)
{
   DoorsChangeState(this, null); // Only fire if subscribed to
}
RichK
A: 

Before invoking an event you must check if the event is null:

if (DoorsChangeState != null)   
  DoorsChangeState(this, null);

When DoorsChangeState is null that means there are no listeners on that event.

Igor Zevaka
+8  A: 

The recommended way to call an event is

var handler = this.DoorsChangeState;
if (handler != null)
    handler(this, null);

The reason for copying the handler locally is incase the event handler changes on another thread while you're checking for null.

EDIT: Found the article talking about race conditions. http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

Cameron MacFarland
+1 Didn't realise the thread safety issues there and the fact that events are immutable. Thanks for the link.
Igor Zevaka
A: 

You need to check to see if the event has been subscribed to.

I use this standard form for throwing all of my events.

var temp = EventName;
if(EventName!= null)
   temp(this, null);
Alastair Pitts
+3  A: 

I know this question has been discussed (and answered) several times here on SO.

Also somewhere here i got the following extension methods to make this pattern more easy to use:

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

    public static void FireEvent(this EventHandler handler, object sender)
    {
        var temp = handler;
        if (temp != null)
        {
            temp(sender, EventArgs.Empty);
        }
    }
}

So in your code you can say:

public bool IsDoorOpen
{
    get { return isDoorOpen;}
    private set
    {
        isDoorOpen = value;
        DoorsChangeState.FireEvent(this);
    }
}
Oliver
+1 That makes a very nice syntax!
MPritch