В обзоре кода я наткнулся на этот (упрощенный) фрагмент кода, чтобы отменить регистрацию обработчика событий:
Fire -= new MyDelegate(OnFire);
Я думал, что это не отменяет регистрацию обработчика события, потому что он создает новый делегат, который никогда не был зарегистрирован раньше. Но в поисках MSDN я нашел несколько примеров кода, которые используют эту идиому.
Итак, я начал эксперимент:
internal class Program
{
public delegate void MyDelegate(string msg);
public static event MyDelegate Fire;
private static void Main(string[] args)
{
Fire += new MyDelegate(OnFire);
Fire += new MyDelegate(OnFire);
Fire("Hello 1");
Fire -= new MyDelegate(OnFire);
Fire("Hello 2");
Fire -= new MyDelegate(OnFire);
Fire("Hello 3");
}
private static void OnFire(string msg)
{
Console.WriteLine("OnFire: {0}", msg);
}
}
К моему удивлению, произошло следующее:
-
Fire("Hello 1");
вышло два сообщения, как и ожидалось. -
Fire("Hello 2");
создано одно сообщение!
Это убедило меня в том, что работают дезарегистрирующие делегатыnew
! -
Fire("Hello 3");
выбралNullReferenceException
.
Отладка кода показала, чтоFire
являетсяnull
после отмены регистрации события.
Я знаю, что для обработчиков событий и делегата компилятор генерирует много кода за сценой. Но я до сих пор не понимаю, почему мои рассуждения ошибочны.
Что мне не хватает?
Дополнительный вопрос: из-за того, что Fire
есть null
, когда нет зарегистрированных событий, я делаю вывод, что везде, где происходит событие, требуется проверка против null
.