Когда вы должны переопределить OnEvent, а не подписываться на событие при наследовании

Когда нужно делать следующее?

class Foo : Control { protected override void OnClick(EventArgs e) { // new code here } } 

В отличие от этого?

 class Foo : Control { public Foo() { this.Click += new EventHandler(Clicked); } private void Clicked(object sender, EventArgs e) { // code } } 

Переопределение, а не присоединение делегата приведет к созданию более эффективного кода, поэтому рекомендуется, когда это возможно, всегда делать это. Для получения дополнительной информации см. Эту статью MSDN . Вот уместная цитата:

Защищенный метод OnEventName также позволяет производным classам переопределять событие без присоединения к нему делегата. Производный class должен всегда вызывать метод OnEventName базового classа, чтобы гарантировать, что зарегистрированные delegates получают событие.

Мероприятие предназначено для внешних абонентов. Когда вы получаете некоторый контроль, всегда переопределяйте метод OnEvent вместо подписки на событие. Таким образом, вы можете быть уверены, когда вызывается код, потому что фактическое событие запускается, когда вы вызываете base.OnEvent (), и вы можете вызывать это перед вашим кодом, после вашего кода, в середине вашего кода или нет все. Затем вы также можете отреагировать на возвращаемые значения из события (т. Е. Изменили свойства в объекте EventArgs).

Имейте в виду, что (по крайней мере, в .NET 2.0) я нашел несколько мест в структуре (особенно в classе DataTable), где метод OnFoo вызывается только тогда, когда было обработано соответствующее событие Foo! Это противоречит руководящим принципам проектирования каркаса, но мы застряли с ним.

Я обошел это, обработав событие с помощью фиктивного обработчика где-нибудь в classе, например:

 public class MyDataTable : DataTable { public override void EndInit() { base.EndInit(); this.TableNewRow += delegate(object sender, DataTableNewRowEventArgs e) { }; } protected override void OnTableNewRow(DataTableNewRowEventArgs e) { base.OnTableNewRow(e); // your code here } } 

Если вы переопределяете, как комментарии Kent Boogaart, вам нужно быть осторожным, чтобы перезвонить base.OnClick, чтобы разрешить напоминания о событиях

Унаследованный class никогда не должен подписываться на свои собственные события, или это события базового classа.

Теперь, если у classа есть экземпляр другого, другого classа в нем, тогда он может потреблять события этого classа и определять, должен ли он поднимать свое собственное событие или нет.

Например, недавно я просмотрел class списка MRU. В нем было несколько элементов управления ToolStripMenuItem, чье событие клика я использовал. После того, как событие click было уничтожено, я затем поднял событие своего classа. ( см. здесь исходный код )

Подписка на событие предназначено для управления для мониторинга событий на другом элементе управления. Для мониторинга вашего собственного события OnClick в порядке. Обратите внимание, однако, что Control.OnClick обрабатывает эти подписанные события, поэтому обязательно вызывайте их в своем переопределении.