Каков предпочтительный метод для обработки событий в C #? - PullRequest
3 голосов
/ 11 февраля 2009

Какой предпочтительный / рекомендуемый способ обработки событий в .NET:

this.Load += new EventHandler(Form1_Load);
private void Form1_Load(object sender, EventArgs e)
{ }

или

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
}

Какими будут плюсы / минусы каждого метода? За последние годы я использовал оба метода и обычно больше склонялся к первому методу просто потому, что именно это Visual Studio создает автоматически для обработки событий. Есть ли какие-то преимущества во втором методе, который мне не хватает?

Ответы [ 5 ]

8 голосов
/ 11 февраля 2009

Первый способ - это то, что предлагает Microsoft. Узор:

  1. какой-то код хочет вызвать событие, вызывает OnXxx
  2. OnXxx звонит делегату
  3. Проводные обработчики событий называются

Если вы выполняете вторую модель, вы рискуете забыть вызов base.OnXxx и все сломать. Приятной частью варианта 2 является то, что вы решаете, вызывать ли вас до или после всех других обработчиков событий. Если вы помещаете свой код перед base.OnXxx, вы выполняетесь раньше, чем это делает событие. Конечно, первая модель может использоваться всегда, вторая только в том случае, если вы создаете подкласс класса, вызывающего событие.

5 голосов
/ 11 февраля 2009

Это полностью зависит от того, где вы хотите поймать событие и почему.

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

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

1 голос
/ 11 февраля 2009

Хотя это не оригинальный вопрос, я хочу отметить, что:

this.Load += new EventHandler(Form1_Load);

можно записать как:

this.Load += Form1_Load;

Предполагаемая конструкция делегата.

0 голосов
/ 11 февраля 2009

Нет жесткого и быстрого правила, но есть хитчи с обоими подходами. Вы выбираете тот, который вы можете легко избежать.

Делегаты

Многие разработчики размещают код + = там, где его можно вызывать повторно. По крайней мере, многие новички делают это. В результате в списке делегатов будет содержаться 'n' записей, поддерживаемых контролем владельца, и все они будут вызваны. Простой способ избежать - это помещать вызовы + = в место конструктора, которое вызывается только один раз.

OnXXXX

Риск заключается в том, что вы забудете вызвать методы base.XXX. Это было распространенным источником ошибок, и большинство программистов Windows знают о проблемах, если вы пропустите вызов версий базового класса - это особенно относится к сообщениям Windows (рисование и т. Д.).

0 голосов
/ 11 февраля 2009

Переопределенный метод предпочтительнее, так как он будет вызываться полиморфно виртуально CLR.

[Редактировать] Вот почему я считаю, что переопределенный метод предпочтительнее:

Вот простой пример:

class Foo
{
    public event EventHandler Changed = delegate { };

    protected virtual void OnChanged()
    {
        this.Changed(this, EventArgs.Empty);
    }
}

class Bar : Foo
{
    public Bar()
    {
        this.Changed += new EventHandler(this.Bar_Changed);
    }

    void Bar_Changed(Object sender, EventArgs e) { }
}

class Baz : Foo
{
    protected override void OnChanged() 
    { 
        base.OnChanged();
    }
}

Теперь я считаю, что Baz - лучшая реализация, и вот почему. Bar должен выполнить следующие инструкции IL, чтобы подключить событие:

    L_000a: ldftn instance void Bar::Bar_Changed(object, class [mscorlib]System.EventArgs)
    L_0010: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
    L_0015: call instance void Foo::add_Changed(class [mscorlib]System.EventHandler)

Мы должны создать делегат для метода обработки, экземпляр EventHandler, а затем вызвать метод add_Changed для события в базовом классе. Хотя они не являются убийцами производительности, для работы Baz ни один из предыдущих кодов не требуется. Поскольку любой вызов OnChanged будет виртуальным, единственным снижением производительности будет CLR, который найдет правильный метод экземпляра для вызова в цепочке наследования.

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