Соглашение о методе поднятия обработчика событий
Я просто просматривал и наткнулся на этот вопрос:
Ответ от nobug включал этот код:
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null)
handler(this, e);
}
Resharper также генерирует подобный код при использовании быстрого исправления "создать метод повышения".
Мой вопрос: зачем нужна эта строка?
var handler = Leave;
Почему это лучше, чем писать это?
protected virtual void OnLeave(EmployeeEventArgs e) {
if (Leave != null)
Leave(this, e);
}
3 ответа
Это лучше, потому что есть небольшая вероятность того, что Leave
становится нулевым после проверки нуля, но перед вызовом (который заставил бы ваш код бросить NullReferenceException
). Поскольку тип делегата является неизменным, если вы сначала назначите его переменной, эта возможность исчезнет; Ваши локальные копии не будут затронуты изменениями Leave
после назначения.
Обратите внимание, что этот подход также создает проблему в обратном порядке; это означает, что существует (крошечная, но существующая) вероятность того, что обработчик события будет вызван после его отсоединения от события. Этот сценарий, конечно, должен быть обработан также изящно.
В многопоточном приложении вы можете получить исключение нулевой ссылки, если вызывающий отменяет регистрацию в событии. Присвоение локальной переменной защищает от этого.
Скорее всего, вы никогда не увидите это (пока это не повредит вам хуже). Вот способ взглянуть на это, который показывает проблему...
protected virtual void OnLeave(EmployeeEventArgs e) {
if (Leave != null) //subscriber is registered to the event
{
//Subscriber unregisters from event....
Leave(this, e); //NullReferenceException!
}
}