Как правильно отменить регистрацию обработчика событий
В обзоре кода я наткнулся на этот (упрощенный) фрагмент кода, чтобы отменить регистрацию обработчика событий:
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
необходимо.