Обработка событий и делегаты
Обработка событий с точки зрения ООП
Предыдущие версии Visual Basic убедительно показали, что модель программирования, управляемая событиями и основанная на применении объектов, повышает производительность труда программиста. Стоило вам перетащить элемент на форму, как он начинал реагировать на определенные события.Передача данных функциям, вызываемым в результате событий
Конечно, вы можете определить собственную сигнатуру для методов объекта-приемника, вызываемых источником, однако в .NET существует практически общепринятое правило, согласно которому функции приемника передаются два параметра: | Объектная переменная, содержащая ссылку на объект-источник события.Простейшее инициирование событий
Давайте вернемся к простому классу Employee и подробно, шаг за шагом разберем все, что необходимо сделать для определения и инициирования событий. Предположим, событие должно инициироваться при попытке увеличения заработной платы более чем на 10 процентов без ввода пароля.Подключение приемников к источнику
В нашем распоряжении имеется весь код, необходимый для рассылки событий, но пока нет ни одного заинтересованного получателя. Существует несколько способов, которыми класс может сообщить VB.NET о своем желании получать события от другого класса.Все вместе
А теперь давайте объединим все сказанное на практическом примере. Создайте консольное приложение и включите следующий фрагмент в первый (стартовый) модуль: | Module Modulel | Private WithEvents anEmployee As EmployeeWithEvents | Sub Main() | Dim tom As New EmployeeWithEvents("Tom".Построение классов событий
В предыдущем примере мы воспользовались готовым классом System.EventArgs. Возможности этого класса весьма ограничены, поскольку его конструктор вызывается без аргументов. При более профессиональном подходе в программе определяется новый класс события, дополняющий этот базовый класс.Динамическая обработка событий
Основной проблемой синтаксиса WithEvents является его недостаточная гибкость. Обработчики событий нельзя динамически устанавливать и отключать на программном уровне – фактически вся схема обработки событий жестко фиксируется в программе.Отключение обработчиков событий. Обработка событий в иерархии наследования.
Обработчики событий, динамически назначаемые командой AddHandler, отключаются командой RemoveHandler, которой должны передаваться точно такие же аргументы, как и при соответствующем вызове AddHandlеr. | Обычно для удаления динамически назначаемых обработчиков хорошо подходит метод Dispose.Делегаты
При использовании механизма обратного вызова приходится выполнять вспомогательные операции для регистрации вызываемых функций. В оставшейся части главы будет показано, что при этом происходит и как при помощи этих операций добиться максимальной эффективности обратного вызова.Создание делегата
Начнем с создания простейшего делегата, инкапсулирующего объект и "указатель" на процедуру этого объекта. Как показано ниже, синтаксис создания объектов чуть сложнее синтаксиса, используемого при создании простых объектов.Практический пример: специализированная сортировка
Предыдущие примеры выглядят искусственно и относятся к категории "игрушечных программ". В этом разделе мы покажем, как использовать делегаты при специализированной сортировке – одной из стандартных областей применения функций обратного вызова.Групповые делегаты
В приведенных выше примерах в делегате инкапсулировался адрес одной функции или процедуры. Нередко в делегатах требуется инкапсулировать сразу несколько процедур (инкапсуляция нескольких функций особого смысла не имеет – каким должно быть возвращаемое значение?).Групповые делегаты как члены классов. Делегаты и события.
В предыдущем примере все модули имеют доступ ко всем функциям остальных модулей. Такую архитектуру нельзя признать удачной – правильнее было бы оформить делегат в виде члена класса, нежели в виде открытого объекта.