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