4

It sounds crazy but I created an event in the class and tried to raise it without having anyone registering to it. However it would give an exception. Is it necessary to have someone register to it before raising the exception? If so then what are the work arounds?

Umair Ahmed
  • 11,238
  • 5
  • 33
  • 39

7 Answers7

14

yes, an event with no-one registered on it is null. The standard way of firing events is:

event EventHandler MyEvent;

private void FireMyEvent(EventArgs e) {
    var handler = MyEvent;
    if (handler != null)
        handler(this, e);
}

Eric Lippert has written a fantastic article on why this pattern is the 'correct' way of firing events

thecoop
  • 45,220
  • 19
  • 132
  • 189
  • Thanx for the link. makes it a complete answer. +1 – Umair Ahmed Oct 02 '09 at 12:08
  • from the link: Why the temp? The temporary variable ensures that this is “thread safe”. If the event’s handlers are being modified on another thread it is possible for Foo to be non-null at the point of the check, then set to null on a different thread, and then the invocation throws. – Umair Ahmed Oct 02 '09 at 12:10
5

Yes. If there are no subscribers, the event will be null and you will get a NullReferenceException when you call it. The correct way of doing the check is as thecoop has said, but there is a simple "shortcut":

public event EventHandler Event = delegate {};

This causes the event to have a default subscriber that does nothing, and so will not throw an exception if there are subscribers. There is a slight performance overhead of doing this, but it does remove the need to check for nulls.

adrianbanks
  • 81,306
  • 22
  • 176
  • 206
  • 1
    see this : http://stackoverflow.com/questions/170907/is-there-a-downside-to-adding-an-anonymous-empty-delegate-on-event-declaration for the performance considerations to using empty delegates. – Lee Treveil Oct 02 '09 at 12:50
3

In .NET, events are (by default) handled as multicast delegates. This means that until you assign the first event handler to the event, the event reference will evaluate as null.

This has lead to the typical way to raise an event being:

public event EventHandler Event;

protected virtual void OnEvent(EventArgs e)
{
    EventHandler @event = Event; // Copy immutable delegate for thread safety.
    if(@event != null) // Check for null.
        @event(e); // Raise event.
}
Paul Turner
  • 38,949
  • 15
  • 102
  • 166
1

Check for null.

if (Object.Event != null) Object.Event();

HTH Alex

Alex Duggleby
  • 7,948
  • 5
  • 37
  • 44
1

If no one has subscribed to the event, the event object is null. It is a common practice to use a OnEvent-like method, for example (assuming your event is called MyEvent):

public event EventHandler<MyEventArgs> MyEvent;

void OnMyEvent(MyEventArgs args) {
    if(MyEvent != null) MyEvent(this, args);
}

When you have to raise the event, you simply call the OnMyEvent method.

thecoop
  • 45,220
  • 19
  • 132
  • 189
Dario Solera
  • 5,694
  • 3
  • 29
  • 34
1

Just to add you can use extension methods also.

        public static void RaiseSafe<T>(this EventHandler<T> eventHandler, object sender, T args)
        where T : EventArgs
    {
        if (eventHandler != null)
            eventHandler(sender, args);
    }

And use it like this:

MyEvent.RaiseSafe(this,new EventArgs());
Lee Treveil
  • 6,655
  • 4
  • 30
  • 29
  • In this case the temporary variable is redundant, as the act of passing the event handler to the method eliminates the race condition. The null check is still necessary though. – Phil Devaney Oct 02 '09 at 12:45
0

The simplest solution to that problem is to declare the event:

public event EventHandlerType MyEvent = delegate { };

In other words, add = delegate { }; to the end.

Now you don't need to write a load of junk each time you raise the event.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284