C # наследование событий - PullRequest
4 голосов
/ 13 апреля 2011

У меня есть эта программа:

    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);
    }

Есть 2 класса - Один и Два, Два является потомком Один.В классе One (SomethingChanged) объявлено событие, которое инициируется классом One и классом Two.Но взгляните на Two.ChangeSomething - он вызывает событие, вызывая метод базового класса.Однако, если я пытаюсь вызвать событие с использованием необработанного кода, например

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

, я получаю сообщение об ошибке компилятора, говорящее

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

Так что мне просто любопытно, почему я не могу использовать raw'код в классе два, чтобы вызвать событие, но когда я вызываю соответствующее событие функции, возникает?

[EDIT] Нашли здесь некоторые пояснения: C #: вызов унаследованного события

Ответы [ 4 ]

6 голосов
/ 13 апреля 2011

Когда вы объявляете событие, используя ключевое слово «event» в C #, сгенерированный IL фактически содержит два соответствующих элемента: частное поле делегата и средство доступа к событию с той же видимостью, что и объявленное событие. Метод доступа к событию нельзя использовать для запуска события. Он используется только для подписки и отмены подписки на уведомления. Ваш код SomethingChanged(this) использует закрытое поле для вызова делегата, и это закрытое поле недоступно извне класса.

1 голос
/ 13 апреля 2011

код

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

(между прочим, в состоянии гонки) подразумевается вызов Delegate.GetInvocationList на SomethingChanged. Автоматически реализованные события не позволяют вам делать это, если вы не находитесь в классе, в котором определено событие.

Вы могли бы сделать это, если бы вы реализовали событие вручную и предоставили protected доступ к полю делегата, поддерживающему событие.

1 голос
/ 13 апреля 2011
0 голосов
/ 13 апреля 2011

Использование:

this.SomethingChanged += new One.del(one_SomethingChanged);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...