3

I am new in c# development. I just trying to study the delegate feature. Based on the articles and notes I read about delegates, I tried to write a sample code to implement delegate based on what I understood from those notes and articles.

But I am getting an error while running the sample

"Object reference not set to an instance of an object."

What is the problem here ?. or Did I implemented the delegate in correct way ? or Is my concept about delegate is wrong ?..

Please help. Thanks in advance.

I posted my code below.

default.aspx.cs

public partial class _Default : System.Web.UI.Page
{
    TestClass myObject = new TestClass();

    protected void Page_Load(object sender, EventArgs e)
    {
        myObject.MyDelegateEvent += new TestClass.MyDelegate(myObject_MyDelegateEvent);
    }

    void myObject_MyDelegateEvent(object sender, EventArgs e)
    {
        Console.WriteLine("Delegate event called");
    }
}

TestClass

public class TestClass
{
    public delegate void MyDelegate(object sender, EventArgs e);

    public event MyDelegate MyDelegateEvent;

    public TestClass()
    {       
        MyDelegateEvent(this, null); // Here getting error "Object reference not set to an instance of an object."

    }

}
Arun
  • 3,478
  • 8
  • 33
  • 46
  • 2
    You can't fire the event in the constructor. No code could possibly subscribe their event handler until *after* the object is constructed. This is a chicken and egg problem. – Hans Passant Jan 27 '12 at 13:00

4 Answers4

6

What you are trying is: raising the event in the constructor itself, i.e. at the time when there is no subscriber for your event hence MyDelegateEvent is null.

Best option is to null check before raising the event

//Check for not null
if(MyDelegateEvent != null)
{
    MyDelegateEvent(this, null);
}
Maheep
  • 5,539
  • 3
  • 28
  • 47
1

Always test for null before raising the event:

if (this.MyDelegateEvent != null)
{
     // Raises the event here
}

If no handler is attached to your event when it is raised (which is the case here as it's raised in the constructor), a null reference exception can be thrown.

EDIT: For the sake of completeness, when no event argument is used, you should use EventArgs.Empty instead of null:

if (this.MyDelegateEvent != null)
{
    this.MyDelegateEvent(this, EventArgs.Empty);
}

Also, there is a EventHandler delegate that can be used when you do not specify any event argument. This is useful as you don't have to write your own each time.

ken2k
  • 48,145
  • 10
  • 116
  • 176
1

When you declare an event, the event is initialised to null. So, in your TestClass constructor you attempt to fire the event but as the event is null this causes the NullReferenceException you are seeing.

To avoid this you need to register an event handler or check for null before raising the event:

if (MyDelegateEvent != null)
{
    MyDelegateEvent(...)
}

Another trick is to initialise the event to an empty delegate when you create it which means you can skip the null checks.

public event MyDelegate MyDelegateEvent = delegate {}; // registers a delegate that does nothing
Paul Ruane
  • 37,459
  • 12
  • 63
  • 82
0

Minor point about some of the code above. It is possible for MyDelegateEvent to be changed between being checked and used. The recommended form (Framework Design Guidelines) is along the lines of

var del = MyDelegateEvent;
if (del != null) {
    del(...);
}

hth,
Alan.

AlanT
  • 3,627
  • 20
  • 28
  • I don't really agree with that recommendation. See http://stackoverflow.com/questions/786383/c-sharp-events-and-thread-safety for a whole discussion about this issue. – ken2k Jan 27 '12 at 13:42
  • @ken2k Had a look through the thread. Very nice. There is a lot of discussion on the correct way to invoke the delegates in terms of Null checks and state checks. I personally like the extension method mentioned but, if someone is going to use the above 'null check and invoke' method, should they not check for the race condition. Did I miss something where it was said that the race check was not required? – AlanT Jan 27 '12 at 14:30