Соглашение о методе поднятия обработчика событий - PullRequest
6 голосов
/ 17 февраля 2010

Я только что просматривал и наткнулся на этот вопрос:

Действие против события делегата

Ответ от 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 ]

12 голосов
/ 17 февраля 2010

Это лучше, потому что есть небольшая вероятность того, что Leave станет нулевым после проверки на ноль, но перед вызовом (что приведет к тому, что ваш код выдаст NullReferenceException).Поскольку тип делегата является неизменным, если вы сначала назначите его переменной, эта возможность исчезнет;Ваша локальная копия не будет затронута любыми изменениями Leave после назначения.

Обратите внимание, что этот подход также создает проблему в обратном порядке;это означает, что существует (крошечная, но существующая) вероятность того, что обработчик события будет вызван после того, как он был отсоединен от события .Этот сценарий, конечно, должен быть обработан также изящно.

5 голосов
/ 17 февраля 2010

В многопоточном приложении вы можете получить исключение нулевой ссылки, если вызывающий отменяет регистрацию в событии. Присвоение локальной переменной защищает от этого.

Скорее всего, вы никогда этого не увидите (пока это не повредит вам хуже). Вот способ взглянуть на это, который показывает проблему ...

protected virtual void OnLeave(EmployeeEventArgs e) {
  if (Leave != null) //subscriber is registered to the event
  {
    //Subscriber unregisters from event....
    Leave(this, e); //NullReferenceException!
  }
}
1 голос
/ 17 февраля 2010

Вот отличное объяснение Эрика Липперта:

События и гонки

...