Страницы

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

пятница, 12 апреля 2019 г.

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

Всем привет, есть такой вот код
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 ?


Ответ

Событие в 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 для событий полностью бессмысленным. Максимум, для чего его можно использовать - трассировка, логгирование или мокинг.

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

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