1

This is my code:

using System.IO;
using System;

public class MyClass1{

    event Action _myEvent;

    public MyClass1(){
        var m = new MyClass2(_myEvent);
        _myEvent();
    }

}

public class MyClass2{
    public MyClass2(Action _event){
        _event += MyFunction;
    }

    void MyFunction(){
        Console.WriteLine("Hi");
    }
}

class Program
{

static void Main()
    {
        var m = new MyClass1();
    }
}

It seems MyClass2 is not registering to the passed argument _myEvent. Invoking _myEvent causes a NullReferenceException even though MyClass2 should be subscribed. If I make _myEvent public and let MyClass2 register to it directly without using the event argument passed to it, it works correctly. Why is that?

  • possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Preston Guillot Jul 19 '15 at 03:26
  • How do you suppose I create it? I've never seen anyone "create" an event. If I make the event public and register to it directly without using the argument everything works fine though. –  Jul 19 '15 at 03:29
  • Which part do you make public? – DavidG Jul 19 '15 at 03:30
  • @PrestonGuillot The answer in the question you posted does not answer my question. –  Jul 19 '15 at 03:31
  • 2
    try `public MyClass2(ref Action _event)` – Khanh TO Jul 19 '15 at 03:35
  • That worked but why do I need to pass it by reference? Isn't a delegate a class? –  Jul 19 '15 at 03:39

2 Answers2

2

You are getting the NullReferenceException because _myEvent is null after the return from MyClass2 constructor.

In the constructor for MyClass2, when you do _event += MyFunction, that is effectively shorthand for:

_event = (Action)Delegate.Combine(_event, (Action)MyFunction);

So now inside the constructor you have a completely new reference which won't get passed back unless you add the ref keyword to the parameter.

DavidG
  • 113,891
  • 12
  • 217
  • 223
1

There is a problem with references. Try:

public MyClass2(ref Action _event)

Explanation:

When the compiler compiles the code, it generates the event into 2 methods: add_YourEvent and remove_YourEvent and a private delegate containing the reference to the head of the list of registered delegates.

The problem arises because when you pass your object as parameter to the method, they're actually 2 different memory blocks. Changes to the reference inside the method does not affect your variable declared in your MyClass1. So when this line is executed:

_event += MyFunction;

The reference is changed from null to a reference to a delegate, but this only affects the passed in parameter. Your variable's reference (declared in MyClass1) does not change.

Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • When `_event += MyFunction;` is called, `_event` is just a delegate, not an event, despite its name. So it's not really calling the `add_YourEvent` method in this case. – sstan Jul 19 '15 at 03:51