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?
7 Answers
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
- 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
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.
- 81,306
- 22
- 176
- 206
-
1see 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
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.
}
- 38,949
- 15
- 102
- 166
-
It's best to copy Event to a temporary variable to prevent race conditions – thecoop Oct 02 '09 at 12:06
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.
- 45,220
- 19
- 132
- 189
- 5,694
- 3
- 29
- 34
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());
- 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
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.
- 114,894
- 38
- 205
- 284
-
So can we set an event reference to null?? If yes then you better check for nulls. – S M Kamran Dec 09 '09 at 06:21
-
Code in other classes can't assign a new value to a member declared as `event`. They can only use `+=` and `-=`. They cannot remove the empty delegate. – Daniel Earwicker Dec 09 '09 at 08:40