публичное событие EventHandler SomeEvent = делегат {}; - PullRequest
0 голосов
/ 18 февраля 2011

Мне надоело иметь весь этот бесполезный шум в моем коде:

private void RaiseSomeOtherEventIfItIsNotNull()
{
    if (this.SomeOtherEvent != null)
    {
        this.SomeOtherEvent(this, EventArgs.Empty);
    }
}

В 99,9% случаев мне все равно, кто к нему подключен или он нулевой или нет,Просто поднять событие!Я действительно не понимаю, почему компилятор c # заставляет меня писать весь этот шум.

Поэтому я подумал, что мог бы объявить событие, подобное этому:

public event EventHandler SomeOtherEvent = delegate { };

, это позволило бы мнеизбавиться от бесполезной нулевой проверки и бесполезного метода повышения *.Я всегда мог сделать следующее:

this.SomeOtherEvent(this, EventArgs.Empty);

Теперь, когда я сравниваю стандартный подход с «моим» подходом в Reflector Лутца Редера, я вижу некоторые существенные различия.Компилятор переопределил Add{} и Remove{}, есть дополнительный статический экземпляр анонимного делегата:

[CompilerGenerated] 
private static EventHandler CS$<>9__CachedAnonymousMethodDelegate1;

, и есть это:

.method private hidebysig static void <.ctor>b__0(object, class [mscorlib]System.EventArgs) cil managed
{
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
    .maxstack 8
    L_0000: nop 
    L_0001: ret 
}

Теперь мой вопрос: сделатьВы видели какие-либо проблемы или недостатки в удалении событий с инициализацией по умолчанию, подобной этой?

Ответы [ 4 ]

7 голосов
/ 18 февраля 2011

Вы показали дополнительный метод , но не дополнительный класс . Дополнительный метод хорош, IMO - он просто представляет обработчик без операции. Не проблема.

Дополнительный класс несколько удивителен, так как идея в том, что он изменяет поведение добавления / удаления ... компилятор всегда будет создавать методы добавления / удаления для события, поскольку именно это делает его событие.

Лично я думаю, что это нормально - но альтернативой было бы написать методы расширения, например

public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
    where T : EventArgs
{
    if (handler != null)
    {
        handler(sender, args);
    }
}

public static void Raise(this EventHandler handler, object sender,
                         EventArgs args)
{
    if (handler != null)
    {
        handler(sender, args);
    }
}

тогда просто позвоните

myEvent.Raise(this, args);

Это будет работать для всех EventHandler и EventHandler<T> событий.

1 голос
/ 18 февраля 2011

Microsoft использует следующее соглашение:

Объявите событие следующим образом.

public event EventHandler<ChangedArgs> ItemChanged; 

Затем создайте метод вызова

protected virtual void OnItemChanged(ChangedArgs args) 
{
     var handler = ItemChanged; 

     if (handler != null) 
         handler(this, args);
}

Это также ThreadSafeи когда бы ни возникло событие, просто вызовите OnItemChanged

0 голосов
/ 18 февраля 2011

Я могу быть совершенно неправ (и если да, то скажите мне, почему, мне тоже любопытно сейчас), но, возможно, вам нужно объявить делегат события на уровне класса?

public delegate void SomeEvent(object sender, EventArgs e); 

0 голосов
/ 18 февраля 2011

Насколько я могу сказать, нет, поскольку это неоперационные обработчики (поскольку IL генерирует инструкции nop и ret).Назначение пустого обработчика - это почти то же самое, что и отсутствие его вообще, т.е. вы ничего не делаете с этим событием.

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