Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can´t we raise event with accessors?

Tags:

c#

events

Why can´t we raise an event with a custom implementation, while it is possible without them? See this code:

public class Program
{
    private EventHandler myEvent;
    public event EventHandler MyEvent
    {
        add { myEvent += value; }
        remove { myEvent -= value; }
    }

    public event EventHandler AnotherEvent;

    public static void Main()
    {
        var target = new Program();
        target.MyEvent(null, null);       // ERROR CS0079
        target.AnotherEvent(null, null);  // compiles
    }
}

You see both events are declared within my class. While target.AnotherEvent(...) compiles just fine, target.MyEvent(...) does not:

The Event MyEvent can only appear on the left hand side of += or -=.

I Know an event is just a delegate with an add- and remove-method. So AnotherEvent is translated by the compiler to an add- and a remove-method:

private EventHandler _AnotherEvent;
public event EventHandler AnotherEvent
{ 
    add { _AnotherEvent += value; }
    remove { _AnotherEvent -= value; }
}

So I assume the call to AnotherEvent is replaced by the compiler to a call to the private delegate, which was _AnotherEvent(...).

Did I get this right? Are there any docs about why the second call works while the former does not? Or at least any description about what the compiler does here?

like image 674
MakePeaceGreatAgain Avatar asked Oct 29 '18 08:10

MakePeaceGreatAgain


2 Answers

When an auto event is used public event EventHandler AnotherEvent;. The compiler will create a field (and some methods) for it and invoking is done on that field. So the public event does not exists anymore. It's syntactic sugar.

So invoking a non-auto event is not possible. Because it isn't found in the compiled code. It's replaced by add_, remove_ methods. You can only invoke on the private field (which is generated)

This explains why you cannot invoke an event outside the class instance.

like image 144
Jeroen van Langen Avatar answered Oct 14 '22 00:10

Jeroen van Langen


It doesn't work because there is simply now way to get the actual invokeable event handler. As you have noted, there is just an add and remove, not a get.

The generated code for the event handler is:

.event [mscorlib]System.EventHandler MyEvent
{
  .addon instance void ConsoleApp1.Program::add_MyEvent(class [mscorlib]System.EventHandler)
  .removeon instance void ConsoleApp1.Program::remove_MyEvent(class [mscorlib]System.EventHandler)
} // end of event Program::MyEvent

It adds two method references, one for add and one for remove. If you look at it, how would it know what method to invoke? What if add and remove are much more complex than they are now? There is just no way to know for sure what event handler to call.

like image 24
Patrick Hofman Avatar answered Oct 13 '22 23:10

Patrick Hofman