Повышение событий в C #: производительность и элегантность - PullRequest
4 голосов
/ 19 марта 2012

Привыкнув к VB.NET, я привык «просто поднимать события».Конечно, пользовательские события различаются, но с «обычными» событиями - мне не нужно проверять, является ли делегат Nothing перед повышением.

С C # я обнаруживаю, что повторяю этот шаблон:

if (myHandler != null) 
{
    myHandler(this, new EventArgs());
}

Я думал, что следующий шаблон может оказаться более элегантным:

  1. myHandler инициализируется пустой лямбдой: myHandler = (sender, e) => { };
  2. myHandler, как ожидается, никогда не будет нулевымТаким образом, повышение просто станет: myHandler(this, new EventArgs());

Будет ли этот шаблон более или менее производительным, чем предыдущий?Есть ли другие важные соображения, которые я должен принять во внимание?

Ответы [ 4 ]

5 голосов
/ 19 марта 2012

Это что-то дополнительное, что должно произойти в строительстве, но оно не будет огромным. Следует обратить внимание на то, что некоторые инфраструктуры сериализации, такие как DataContractSerializer (WCF), не запускают конструкторы или инициализаторы полей, поэтому, в конце концов, они не могут быть ненулевыми. Лично, если большинство ваших событий EventHandler, у меня может возникнуть соблазн использовать метод расширения:

public static void SafeInvoke(this EventHandler handler, object sender) {
    if (handler != null) handler(sender, EventArgs.Empty);
}

, то:

SomeEvent.SafeInvoke(this);

хотя, честно говоря, у меня редко возникает проблема с простым использованием нулевой проверки; p

Еще одним недостатком является то, что если у вас достаточно событий, что это проблема, вы, вероятно, должны использовать EventHandlerList вместо этого - и этот подход не будет работать с EventHandlerList.

2 голосов
/ 19 марта 2012

Обычной практикой является использование защищенных виртуальных методов OnEventName, где вы можете проверить, является ли событие нулевым, и вызвать его:

protected virtual void OnEventName(parameters)
{
    if (EventName != null)
        EventName(this, new EventNameEventArgs(parameters);
}

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

Кстати, более короткий способ добавить фиктивный обработчик: myHandler = delegate {};

1 голос
/ 19 марта 2012

Я думаю, что разница в производительности между двумя подходами недостаточно велика , чтобы иметь значение.Во всяком случае, я бы сказал, что проверка на нуль * на 1005 * дешевле , чем вызов метода через делегат, даже если это неоперация.

Когда речь идет о элегантность , следует отметить, что ключевое слово RaiseEvent в VB.NET автоматически расширяется компилятором до той же самой конструкции, которую вы должны написать сами в C #:

If (Not MyEvent Is Nothing) Then
  MyEvent.Invoke(New EventArgs())
End If

Если вы хотите избежать повторения этой конструкции во всем коде, вы можете инкапсулировать ее в несколько методов расширения:

public static void RaiseEvent(this EventHandler source, object sender)
{
    if (source != null)
    {
        source.Invoke(sender, new EventArgs());
    }
}

public static void RaiseEvent<T>(this EventHandler<T> source, object sender, T eventArgs)
    where T : EventArgs
{
    if (source != null)
    {
        source.Invoke(sender, eventArgs);
    }
}

Таким образом, вы можете просто сказать:

myEvent.RaiseEvent(this);
myOtherEvent.RaiseEvent(this, new SomeEventArgs());

, чтосемантически эквивалентен стилю, используемому в VB.NET.

1 голос
/ 19 марта 2012

Не думайте, что между 1-м и 2-м случаем имеется существенная разница, по крайней мере, не настолько, чтобы их рассматривать. При слишком частом использовании делегатов отсутствие if (myHandler != null) может, кстати, принести вам некоторые преимущества в производительности. Поэтому, если вы уверены, что обработчик никогда null, избавьтесь от этого элемента управления, и в основном вы сделали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...