Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# : accessing parent class's events not possible?

never came across this before. Here's the sample:

using System;

namespace Testing
{
    public class Test
    {
        public event Action ActionRequired;
    }

    public class ChildTest : Test
    {
        public void DoSomething()
        {
            if (this.ActionRequired != null)
                this.ActionRequired();
        }
    }
}

This won't work, the error being I can only access the event from the base class.

It's not difficult to sail around (add a protected method to the base class that does both check an invocation of the event and call that method from the child classes), but I really wonder what's the idea behind this restriction?

Cheers,

Sebi

like image 315
Sebastian Edelmeier Avatar asked Jan 20 '11 00:01

Sebastian Edelmeier


2 Answers

You cannot invoke events from outside of the class within which they were defined. However, you don't need to; just follow the idiomatic patter of also declaring a protected method to fire said event.

class Whatever
{
    public event EventHandler Foo;

    protected virtual void OnFoo( EventArgs e )
    {
        EventHandler del = Foo;
        if( del != null )
        {
            del( this, e );
        }
    }
}

Now descendants of class "Whatever" can fire the event by calling OnFoo() and passing in the appropriate EventArgs object.

EDIT: In regards to why this is the behavior, Jon Skeet explained it well in another thread (which also means that this question is a duplicate, so voting to close):

When you declare a public field-like event, the compiler creates a public event, and a private field. Within the same class (or nested classes) you can get at the field directly, e.g. to invoke all the handlers. From other classes, you only see the event, which only allows subscription and unsubscription.

like image 136
Ed S. Avatar answered Nov 05 '22 03:11

Ed S.


The syntax you used to declare the event in your example is actually syntactic sugar for something like this:

private Action _actionRequired;
public event Action ActionRequired
{
    add { _actionRequired += value; }
    remove { _actionRequired -= value }
}

(the actual code is a little more complex of course)

The important part here is that the _actionRequired field is private. Only the event itself is public, but it's only a pair of add/remove methods (similar to a property). So the only thing you can do with the event is subscribe to or unsubscribe from it. The field that hold the actual delegate is private, so it can only be accessed from the class that declares it. When you use ActionRequired in the class that declares it, it refers either to the delegate field or the event itself, depending on the context.

But from any other class, only the event is accessible, not the field. That's why you can't invoke the delegate from another class, even a derived class.

like image 3
Thomas Levesque Avatar answered Nov 05 '22 02:11

Thomas Levesque