Страницы

Поиск по вопросам

суббота, 8 февраля 2020 г.

Почему не вызывается событие

#c_sharp


Всем привет, есть такой вот код

using System;
class a
{
    public virtual event EventHandler MyEv;   
    public void StartEvent()
    {
        MyEv(4, EventArgs.Empty);
    }
}
class b : a
{
    public override event EventHandler MyEv;
}
class c
{
    static void Main()
    {
        b B = new b();
        B.MyEv += (o, e) => Console.WriteLine("From class B");
        B.StartEvent();
    }
}


Почему не вызывается обработчик добавленный к типу B, ведь событие было переопределено
в классе B ?
    


Ответы

Ответ 1



Событие в C# это набор из: приватного поля-делегата метода add метода remove метаданных Т.к. в C# (и вообще .NET) нет виртуальных полей, то virtual на event делает виртуальными только методы add / remove. Неявная реализация события приводит к тому, что классы a и b получают каждый свое приватное поле-делегат. И свою пару add/remove, которая работает или с полем из a или с полем из b. Т.е. ваш код эквивалентен следующему: class a { private EventHandler _MyEvField; public virtual event EventHandler MyEv { add { _MyEvField += value; } remove { _MyEvField -= value; } } public void StartEvent() { _MyEvField(4, EventArgs.Empty); } } class b : a { private EventHandler _MyEvField_2; public override event EventHandler MyEv { add { _MyEvField_2 += value; } remove { _MyEvField_2 -= value; } } } т.е. override переопределяет механизм подписки на событие. Но не переопределяет поле, которе используется для вызова в a.StartEvent. При этом поле остается приватным, и добраться до него из класса b не получится. Чтобы все заработало, вам придется делать виртуальным еще и метод StartEvent, и переопределять его в b. Это делает механизм virtual/override для событий полностью бессмысленным. Максимум, для чего его можно использовать - трассировка, логгирование или мокинг.

Комментариев нет:

Отправить комментарий