Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# event inheritance

I have this program:

    class One
    {
        public delegate void del(object o);
        public event del SomethingChanged;

        int x;
        public int X
        {
            get { return x; }
            set { x = value; OnSomethingChanged(this); }
        }

        protected void OnSomethingChanged(object o)
        {
            if (SomethingChanged != null)
                SomethingChanged(o);
        }
    }

    class Two: One
    {
        public void ChangeSomething()
        {
            //if (SomethingChanged != null)
            //    SomethingChanged(this);
            OnSomethingChanged(this);
        }
    }

    static void Main(string[] args)
    {
        One one = new One();
        Console.WriteLine(one.X);
        one.SomethingChanged += new One.del(one_SomethingChanged);
        one.X = 5;
    }

    static void one_SomethingChanged(object o)
    {
        Console.WriteLine(((One)o).X);
    }

There are 2 classes - One and Two, Two is descendant of One. There is event declared in class One(SomethingChanged) and it is triggered by class One and class Two. But take a look at Two.ChangeSomething - it raises event by invoking base class's method. However if I try to invoke event using raw code like

if (SomethingChanged != null)
    SomethingChanged(this);

I'm getting compiler error saying

The event 'One.SomethingChanged' can only appear on the left hand side of += or -= (except when used from within the type 'eventstest.Program.One')

So I'm just curious why I can't use 'raw' code in class Two to raise event but when I invoke a corresponding function event gets raised?

[EDIT] Found some clarification here: C#: Raising an inherited event

like image 927
Blablablaster Avatar asked Feb 25 '23 12:02

Blablablaster


2 Answers

When you declare an event using the "event" keyword in C#, the generated IL actually contains two corresponding elements: a private delegate field and an event accessor with the same visibility as the declared event. The event accessor cannot be used to fire the event. It is only used to subscribe and unsubscribe from notifications. Your SomethingChanged(this) code is using the private field to invoke the delegate, and that private field is not available from outside the class.

like image 176
Nicole Calinoiu Avatar answered Mar 06 '23 14:03

Nicole Calinoiu


The code

if (SomethingChanged != null)
    SomethingChanged(this);

(which has a race-condition, by the way) implies calling Delegate.GetInvocationList on SomethingChanged. Automatically implemented events don't allow you to do that unless you are in the class the event is defined in.

You would be able to do it if you implemented the event manually and provided protected access to the delegate field backing the event.

like image 45
Jon Avatar answered Mar 06 '23 14:03

Jon