C# event inheritance

2019-04-10 00:06发布

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

4条回答
三岁会撩人
2楼-- · 2019-04-10 00:32

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.

查看更多
我想做一个坏孩纸
3楼-- · 2019-04-10 00:36

Use:

this.SomethingChanged += new One.del(one_SomethingChanged);
查看更多
smile是对你的礼貌
4楼-- · 2019-04-10 00:41

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.

查看更多
干净又极端
5楼-- · 2019-04-10 00:51
登录 后发表回答