Это хорошая идея для метода расширения? - PullRequest
4 голосов
/ 29 сентября 2011

Часто я вижу код, подобный этому, разбросанный и дублированный вокруг исходного кода:

var handler = MyEvent;

if (handler != null)
{
    handler.Invoke(null, e);
}

Есть ли причина не просто инкапсулировать его в такой метод расширения?

public static void SafeInvoke<T>(this EventHandler<T> theEvent, object sender, T e) where T : EventArgs
{
    var handler = theEvent;

    if (handler != null)
    {
        handler.Invoke(sender, e);
    }
}

Так что звонки можно сделать так:

MyEvent.SafeInvoke(this, new MyEventArgs(myData));

Ответы [ 3 ]

3 голосов
/ 29 сентября 2011

Это интересный. Джеффри Рихтер много говорил об этом в CLR через C # .

С пустой проверкой, как показано ниже: -

var handler = MyEvent;

if (handler != null)
{
    handler.Invoke(null, e);
}

Компилятор JIT потенциально может полностью оптимизировать переменную handler. Тем не менее, команда CLR знает, что многие разработчики используют этот шаблон для генерации событий и встроили эту информацию в JIT-компилятор. Вполне вероятно, что это останется в силе во всех будущих версиях CLR, потому что изменение поведения может нарушить слишком много существующих приложений.

Нет причины, по которой вы не можете написать метод расширения, чтобы выполнить эту работу за вас (это именно то, что я сделал). Обратите внимание, что сам метод может быть встроен в JIT (но временная переменная все равно не будет оптимизирована).

Если вы планируете использовать ваше приложение против другой среды выполнения, например, Mono (который, я подозреваю, в любом случае отражает поведение CLR в этом случае) или некоторая другая экзотическая среда выполнения, которая может появиться, затем вы можете защитить свой код от возможности JIT-вставки, добавив [MethodImplAttribute(MethodImplOptions.NoInlining)] к вашему методу расширения.

Если вы решите не использовать метод расширения, другой способ защиты от JIT-оптимизации (который рекомендует Джеффри Рихтер) - присвоить значение временной переменной способом, который не может быть оптимизирован компилятором JIT, например

var handler = Interlocked.CompareExchange(ref MyEvent, null, null);
0 голосов
/ 29 сентября 2011

Вы можете создать такой метод расширения, если шаблон вас беспокоит.

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

0 голосов
/ 29 сентября 2011
...