-
Предыдущие версии 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.
-
При использовании механизма обратного вызова приходится выполнять вспомогательные операции для регистрации вызываемых функций. В оставшейся части главы будет показано, что при этом происходит и как при помощи этих операций добиться максимальной эффективности обратного вызова.
-
Начнем с создания простейшего делегата, инкапсулирующего объект и "указатель" на процедуру этого объекта. Как показано ниже, синтаксис создания объектов чуть сложнее синтаксиса, используемого при создании простых объектов.
-
Предыдущие примеры выглядят искусственно и относятся к категории "игрушечных программ". В этом разделе мы покажем, как использовать делегаты при специализированной сортировке – одной из стандартных областей применения функций обратного вызова.
-
В приведенных выше примерах в делегате инкапсулировался адрес одной функции или процедуры. Нередко в делегатах требуется инкапсулировать сразу несколько процедур (инкапсуляция нескольких функций особого смысла не имеет – каким должно быть возвращаемое значение?).
-
В предыдущем примере все модули имеют доступ ко всем функциям остальных модулей. Такую архитектуру нельзя признать удачной – правильнее было бы оформить делегат в виде члена класса, нежели в виде открытого объекта.