• Microsoft .NET
  • C#.NET
  • Возбуждение событий, обработчики событий и использование делегатов

Основы, лучшие методы и соглашения реализации событий в C#

ОГЛАВЛЕНИЕ

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

1. Введение

Все, что вам нужно, чтобы определить, реализовать и понять пользовательские события с помощью C#, изложено в данной статье. Представлены важнейшие компоновочные модули, которые должны использоваться для достижения данных целей, наряду с лучшими методами и соглашениями реализации событий. Данная статья описывает варианты .NET 1.x и 2.0+ для публикации и подписки на события.

Хотя поддержка реализации пользовательских событий была доступна с версии 1.0 среды разработки .NET, с тех пор были  добавлены дополнительная связанная с событиями поддержка и возможности. Некоторые из новых возможностей (например, обобщенный System.EventHandler, безымянные методы, вывод делегатов и т.д.) образуют сокращения, предназначенные для упрощения реализации событий. Хотя такие методы ускоряют реализации событий, предъявление их до или вместо важнейших компоновочных модулей дало бы менее точное представление. Поэтому данная статья избегает таких сокращений до тех пор, пока не будут введены все важнейшие компоновочные модули.

Предположения об аудитории

Данная статья предполагает знания программирования .NET с C#, наряду с пониманием общих средств, внедренных в версию 2.0 среды разработки .NET. Если вы не понимаете общие средства, эта статья все же может быть полезной, так как в ней изложены способы реализации событий, не основанные на общих средствах. В данной статье представлены общие и не общие методы реализации событий.

2. Терминология и определения

Литература, описывающая события и связанные с ними идеи, часто использует множество слов или выражений для описания любого конкретного понятия. Следующий список перечисляет большую часть данной  терминологии с краткими пояснениями идей, лежащих в основе выражений.

событие, предсобытие, постсобытие, и состояние, изменение состояния и ожидаемое изменение состояния

Термин "событие" обычно означает, что произошло или вскоре произойдет изменение в состоянии объекта. Термин также используется в отношении некоторых действий, совершающихся внутри объекта или приложения – таких действий, как обработка знака от конечного пользователя (например, нажата кнопка), или оповещение о прогрессе в течение длительной задачи.

Термин "состояние" ссылается на текущий набор значений одной или более переменных в объекте или приложении. Изменение в состоянии означает, что значение одной или более переменных внутри объекта изменилось. В процессе уведомления о событии изменения в состоянии, или ожидаемые изменения в состоянии, являются главными причинами возбуждения событий. Поэтому есть два способа определить событие, связанное с изменением в состоянии: непосредственно перед изменением в состоянии, или сразу после изменения в состоянии. Первые называются предсобытиями, а последние постсобытиями.

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

публикатор события, источник события, предмет

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

подписчик события, получатель, слушатель, наблюдатель

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

возбудить, запустить, или вызвать событие; уведомление, или уведомление о событии

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

В случаях, когда никакие подписчики [на событие] не были зарегистрированы в публикаторе, событие не возбуждается.
Заметьте, что в данной статье события описаны как "возбужденные" (не "запущенные" или "вызванные"). Это соглашение исходит от группы разработчиков, создавших большую часть среды разработки .NET (Квалина и Абрамс, 2006). Они предпочитают термин, "возбудить", так как он не имеет дополнительных негативных значений выражений "запустить" или "вызвать".

данные о событии, связанные с событием данные, и аргументы события ("event args")

Когда событие возбуждается, публикатор часто включает данные, отправляемые подписчикам посредством процесса уведомления о событии. Эти данные, вероятно, относятся к конкретному событию, которое было возбуждено, и представляют интерес для подписчиков событий.

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

Тип делегата, делегаты

Ясное понимание типов делегатов .NET крайне важно для понимания способа реализации событий в среде разработки .NET. Следовательно, большая часть данной статьи посвящена объяснению связи между делегатами и событиями.

Два значения "обработчика события"

Литература за пределами данной статьи часто использует термин, "обработчик события", в отношении (1) делегата, на основе которого определено событие (в публикаторе), или (2) любого метода, зарегистрированного в событии (в подписчике). Более того, Intellisense("интеллектуальное восприятие") в Visual Studio ссылается на метод обработки события (в подписчике) просто как на "обработчик". Для ясности данная статья использует выражение "обработчик события" в отношении делегата, тогда как выражение "метод обработки события" используется в отношении любого метода, зарегистрированного в событии.

Для обобщения: "обработчик события" – делегат, на котором событие основано, тогда как "метод обработки события" – метод, вызываемый в подписчике, когда событие возбуждается.

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

События .NET и шаблон наблюдателя GoF

События, реализованные в среде разработки .NET и описанные в данной статье, образуют оптимизированную реализацию .NET шаблона наблюдателя, документированного "бандой четырёх" или "GoF" (Гамма и другие, 1995). Механизмы .NET, используемые для реализации событий (особенно делегатов), существенно сокращают объем работ, требуемый для реализации шаблона наблюдателя в приложениях .NET.