Г. Шилдт - С#4.0 Полное руководство (1160795), страница 95
Текст из файла (страница 95)
Это означает, что каждый объект класса х должен быть зарегистрирован отдельно, чтобы получать уведомления о событиях. Для демонстрации этого факта в данной программе производится групповая адресация события трем отдельным объектам класса х. /* Уведомления о событиях получают отдельные объекты, когда метод экземпляра используется в качестве обработчика событий.
*/ няъпч Яуясев; // Объявить тип делегата для события. де1едяте чогд Мукчепснапд1ег()у // Объявить класс, содержащий событие. с1аяя МУЕчепт ( роЬ11с ечепг муечепгнапд1ег яовеечепгл // Этот метод вызывается для запуска события. рпЬ1гс чо1д ОпзовеЕчепс() ( 1Г(зовеЕчепс != пп11) ЯовеЕчепт(); ) ) с1аяз Х ( гпг гд/ рибггс Х(гпт х) ( 1д = х) ) // Этот метод экземпляра предназначен в качестве обработчика событий. рпбтгс чо1д ХЬапд1ег() ( сопяо1е.иггсеьтпе("событие получено объектом " + тд)/ ) ) с1аяя Ечептбевоз ( ятатгс чо1д Мягп() ( муечепг ечг = пен муечепг(); Х о1 = пен Х(1); Х о2 = пен Х(2); Х оз = пен Х(З); ечг.ЯовеЕчепс += о1.ХЬапд1ег; ечс.яовекчепс += о2.ХЬапд1ег; ечГ.Яовекчепс += оЗ.ХЬапд1ег; Глава 1б.
Делегаты, события и ляыбда-вырав[ения 499 Запустить событие. ечЫОпзовеЕчепг(); Выполнение кода из этого примера приводит к следующему результату. Событие получено объектом 1 Событие получена объектом 2 Событие получено объектом 3 Как следует из результата выполнения кода из приведенного выше примера, каждый объект должен зарегистрировать свой интерес в событии отдельно, и тогда он будет получать отдельное уведомление о событии. С другой стороны, когда в качестве обработчика событий используется статический метод события обрабатываются независимо от какого-либо объекта, как демонстрируется в приведенном ниже примере программы.
/* Уведомления о событии получает класс, когда статический метод используется я качестве обработчика событий. */ оя1пч Яуясевг УУ Объявить тип делегата для события. с)е1есаее ноьб МУЕчепеняпб1ег (); // Объявить класс, аодеркащий событие. с1аяя Мукнепг ( раЫьс ечепс Муенепснапс)1ег яовеечепги /! Этот метод вызывается для запуска события. раЫ1с чогб Опзовекнепт() ( 1Г(зовевчепг != па11) ЯовеЕчепг()г ) с1аяя Х ( /* Этот статический метод предназначен я качестве обработчика событий.
*/ роЫ1с ягаеьс чо16 Хпапд1ег[) ( Сопяо1е.нгьее11пе["Событие получено классом."); с1аяя ЕнепСРевол ( ягаггс чоза Маьп() ( Иукчепг ечг = пен ИУЕчепг() ечс.яовеенепс += х.хьапб1егг // ЗапУстить событие. ечг.опяовеЕчепг()) ) ) 500 Часть!. Язык С() При выполнение кода этого примера получается следующий результат. Событие получено классом. Обратите в данном примере внимание на то, что объекты класса Х вообще не создаются. Но поскольку Х)тапс(1ег () является статическим методом класса Х, то он может быль привязан к событию ЕовеЕчепс и выполнен при вызове метода ОпзовеЕчепг(). Применение аксессоров событий В приведенных выше примерах собьпия формировались в форме, допускавшей автоматическое управление списком вызовов обработчиков событий, включая добавление и удаление обработчиков событий из списка.
Поэтому управление этим списком не нужно было организовывать вручную. Благодаря именно этому свойству такие события используются чаще всего. Тем не менее организовать управление списком вызовов обработчиков событий можно и вручную, чтобы, например, реализовать специальный механизм сохранения событий. Для управления списком обработчиков событий служит расширенная форма оператора ечепс, позволяющая использовать аксессоры событий. Эти аксессоры предоставляют средства для управления реализацией подобного списка в приведенной ниже форме.
ечепс делегат события нмя события ( абб ( Код добавления события в цепочку событий. ) гевоче ( /! Код удаления события нз цепочки событий. ) ) В эту форму входят два аксессора событий: ас(д и гевоче. Аксессор абб вызывается, когда обработчик событий добавляется в цепочку событий с помощью оператора '-=. В то же время аксессор гевоче вызывается, когда обработчик событий удаляется из цепочки событий с помощью оператора -=. Когда вызывается аксессор абб или гевоче, он принимает в качестве параметра добавляемый или удаляемый обработчик.
Как и в других разновидностях аксессоров, этот неявный параметр называется ча1це. Реализовав аксессоры абб или гевоче, можно организовать специальную схему хранения обработчиков событий. Например, обработчики событий можно хранить в массиве, стеке или очереди. Ниже приведен пример программы, демонстрирующей аксессорную форму события. В ней для хранения обработчиков событий используется массив.
Этот массив состоит всего из трех элементов, поэтому в цепочке событий можно хранить одновременно только три обработчика. Создать специальные средства для управления списками вызова обработчиков событий. цвьпй Зувсев; Объявить тнп делегата дпя события. с(втедаве чогб МуЕчепонвпг(гег()т Глава 15. Делегаты, события и лаибда-выражеиия 501 // Объявить класс для хранения максимум трех событий. с1аяя МуЕчепс МуЕчепГНапб1ег() ечпг = пеи МуЕчепГНапб1ег(3]; рпЬ1го ечепв МуЕнепввапб1ег Яошевчепв ( Лобавить событие в список. ав)О ( 1пг 1; Гог(1=0; 1 < 3; 1в+) 10(енпв(1] == пп11) ( ечпв(1) = на1ое) Ьгеатм ) — 3) Сопяо1е.иг1сеЬгпе("Список событий заполнен."); ) // Удалить событие из списка.
гешоче ( Ьпг Гог(г=о; 1 < 3; 1++) 11(ечпс(1] == на1пе) ( енпг(1) = пп11; Ьгеаты ) 11 (1 == 3) Сопяо1е.Иг1геЬгпе("Обработчик событий не найден.") ) // Этот,метод вызывается для запуска событий. роЪ1гс чоуб ОпЯошеЕчепс () ( Гог(гпв г=о; г < Зг 1+т) 11 (енпс (1] ! = по11) ечпс [1] (); ) // Создать ряд классов, используюших делегат МувчепСНапб1ег. с1аяя И ( роЬЬгс ного ИЬапд1ег() ( Сопяо1е.иглсеЬгпе("Событие получено объектом И")г ) с1авв Х ( рсЬ11с чо10 ХЬапд1ег() ( Сопяо1е.иггвеЬгпе("Событие получено объектом Х") ) ) с1аяв Х ( рсЬ1гс ного УЬапс)1ег() ( Сопво1е.иггсеЬгпе("Событие получено объектом У") ) 502 Часть 1.
Язык С(г с1аяя Е ( рцЬ11с чотд 2Ьапб1ег() ( Сопяо1е.игдгеЬьпе("Событие получено объектом Е") ) ) с1аяя Ечепгоевоб ( ягаС1с чо1б Мадп() ( МуЕчепС ечС = пеи МуЕчепС() И нОЪ = лен И(); Х хОЬ = пен Х(); У УОЬ = У(); Е гОЬ = пею Е()) // Добавить обработчики в цепочку событий, Сопяо1е.нгьсесдпе("Добавление событий.")1 ечС.ЯовеЕчепг ь= нОЬ.ИЬапб1ег) ечг.зоВЕЕчепг += хОЬ.ХЬапб1ег; ечг.зовекчепС Ь= УОЬ.тлапб1егт // Сохранить нельзя — список заполнен. ечС.ЯовеЕчепС += яОЬ.2Ьапд1ег) Сопяо1е.нгЕСеььпе()) // Запустить события.
ечг.опЯовеЕчепг()," Сопяо1е.Иг1Се21пе(); // Удалить обработчик. Сопяо1е.кгггесгпе("Удаление обработчика хОЬ.ХЬапд1ег.") ечС.Яовевчепг =- хОЬ.ХЬапб1ег; ечг.опзовекчепг()) Сопяо1е.игдгевзпе() // Попробовать удалить обработчик еще раз. Сопяо1е.нг1Сесспе("Попытка удалить обработчик " "хОЬ.ХЬапб1ег еще раз.")) ечг.зовеЕчепг =- хОЬ.ХЬапд1ег( ечс.опзовеЕчепг(); Сопяо1е.нгггеьгпе() // А теперь добавить обработчик 2Ьапб1ег. Сопяо1е.нгдге11пе("Добавление обработчика яОЬ.2Ьапд1ег.") ечг.зовеЕчепг += яОЬ.ЕЬапб1ег) ечг.опЯовеЕчепс(); ) Ниже приведен результат выполнения этой программы: Добавление событий.
Список событий заполнен. Глава 15. Аевегаты, события я вямбда-выражения 503 Событие получено объектом И Событие получено объектом Х Событие получено объектом У Удаление обработчика хОЬ.ХЬапб1ег. Событие получено объектом И Событие получено объектом т Попытка удалить обработчик хОЬ.ХЬапб1ег еще раз. Обработчик событий не найден. Событие получено объектом И Событие получено объектом У Добавление обработчика гОЬ.ЗЬапб1ег. Событие получено объектом И Событие получено объектом Х Событие получено объектом Рассмотрим данную программу более подробно. Сначала в ней определяется делегат обработчиков событий МуЕчепснапс(1ег. Затем объявляется класс муЕчепс. В самом его начале определяется массив обработчиков событий ечпс, состоящий из трех элементов. МувчепГНапб1ег(] ечпс = пен МуЕчепГНапб1ег[3]; Этот массив служит для хранения обработчиков событий, добавляемых в цепочку событий.
По умолчанию элементы массива ечпс инициализируются пустым значением [пп11). Далее объявляется событие НоыеЕчепс. В этом объявлении используется приведенная ниже аксессорная форма оператора ечепс. рпЬ11с ечепс МуЕнепГНапб1ег ЯотеЕчепс ( // Добавить событие в список. або ( гпг 1; Гог(1=0) г < 3) 1++) 1г (ечпг[].) == па11) ( ечпс[г) = ча1пе; Ьгеа)с) ) (1 == 3) Сопао1е.нггсеьгпе("Список событий заполнен."); // Удалить событие из списка. гавоте ( гпг Гог(г=О; 1 < 3; 1++) 1Й(ечпг(1) == ча1пе) ( ечпс(г) = пп11; Ьгеак; ) 11 (г == 3) Сопзо1е.ыггсеьгпе("Обработчик событий не найден.") ) ) 504 Часть Е Язык С(г Когда в цепочку событий добавляется обработчик событий, вызывается аксессор агггг, и в первом неиспользуемом (т.е. пустом) элементе массива ечпг запоминается ссылка на этот обработчик, содержащаяся в неявно задаваемом параметре ча1ое.
Если в массиве отсутствуют свободные элементы, то выдается сообщение об ошибке. (Разумеется, в реальном коде при переполнении списка лучше сгенерировать соответствукзщее исключение.) Массив ечпс состоит всего из трех элементов, поэтому в нем можно сохранить только три обработчика событий.