3

Why would a 'public event EventHandler cccc' be null?

I have a class that's

public class Builder
{
    public event EventHandler StartedWorking;

    public Builder()
    { 
        // Constructor does some stuff
    }

    public void Start()
    {
       StartedWorking(this, eventargobject); //StartedWorking is null --
    }
}   

This seems straightforward and something I do all the time? Am I missing something obvious or is there something that could cause this?

EDIT:

Does this mean that if I fire an event that is not subscribed to in a client class I have to check that it is not null?

EDIT-2:

I guess I'd never had events that were never not subscribed to and hence never ran into this -- You learn something new every day Sorry about the seemingly stupid question....

Matt
  • 25,943
  • 66
  • 198
  • 303
  • Matt: Regarding your edit - I added the "correct" way to raise events to my answer for you. You should always check for null first. – Reed Copsey Jun 17 '10 at 18:38

4 Answers4

15

The event handler will be null unless somebody has subscribed to the event. As soon as a delegate is subscribed to the event, it will no longer be null.

This is why it's always suggested to use the following form for raising events:

public void Start()
{
    var handler = this.StartedWorking;
    if (handler != null)
    {
         handler(this, eventArgObject);
    }
}

This protects you from a null exception if there has been no subscribers.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
3

As others have already said, it's null because there are no subscribers.

To answer your edit: Yes, you should always check an event for null before triggering it. However, if you just do a plain if(StartedWorking != null){...} you risk a race condition, because it's possible for a subscriber to unsubscribe after the null check but before you trigger the event. Because of this, you should always use this pattern when checking events for null:

protected void OnStartedWorking()
{
    EventHandler localEvent = StartedWorking
    if(localEvent != null)
    {
        localEvent(this, EventArgs.Empty);
    }
}

This prevents the race condition by taking a copy of the event first so the subscribe list is fixed at the point of copying.

There's more infomration about publishing events on MSDN: How to Publish Events that Conform to .NET Framework Guidelines

(This works because in .net the MultiCastDelegate class in imutable, so any attempt to change the subscriber list on the event won't effect the copy you have made)

Simon P Stevens
  • 27,303
  • 5
  • 81
  • 107
0

If you haven't hooked any event subscribers up to your StartedWorking event, then it will be null. That is how .NET events works.

This article, among other things, demonstrates that you should check for null before invoking an event. This other question and answer demonstrates how you can create events in a way that avoids the null check (basically by adding an empty handler always).

Community
  • 1
  • 1
driis
  • 161,458
  • 45
  • 265
  • 341
  • The first article (from .NET 1.1) shows how to do it, but it's inappropriate in multithreaded situations. I recommend my approach instead. The second article works, but can be brittle (it's possible to remove that handler, which will cause the exception again), plus it adds overhead every time you raise the event (a delegate invocation). – Reed Copsey Jun 17 '10 at 18:46
0

Don't you need to assign a function ?

StartedWorking += new EventHandler(afunction);

void afunction(object sender, EventArgs e)
{
   DoSomething();
}
Julian de Wit
  • 3,084
  • 2
  • 29
  • 29