Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Медведев_С++_CLI_C#_Java_J#.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆

Void main ()

{

// Создать объект класса А

A ^a= gcnew A();

// Инициировать и сгенерировать глобальное событие

Console::WriteLine ( "----DelGlob----" ) ;

a -> evGlob+= gcnew DelGlob (&B::Handler);

a -> GenerateGlob ("First");

// Инициировать и сгенерировать локальное событие

Console::WriteLine ("----2----DelLoc----");

a -> evLoc+= gcnew A::DelLoc (&B::Handler);

a -> GenerateLoc ("First");

Console::ReadKey();

}

Результат:

----DelGlob----

DelGlob: First

Получил: First

----2----DelLoc----

DelLoc: First

Получил: First

В программе примера 8.3.1 объявлен делегат DelGlob вне класса и делегат DelLoc внутри класса. Но вместо ссылок и дескрипторов на объекты делегатов в класс А помещены ссылки и дескрипторы на объекты событий.

Объявлению ссылки предшествует слово event, а объявлению дескриптора – также event. Интерфейсные функции GenerateGlob() и GenerateLoc() генерируют соответственно события глобального делегата DelGlob и события локального делегата DelLoc.

Чрезвычайно важно обратить внимание на строки программы, признанные компилятором ошибочными. Из них следует, что в отличие от делегата, событие нельзя выполнять вне объекта, в классе которого это событие объявлено !

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

Важно отметить, что как событие связано с определённым объектом, также и обработчики других объектов связаны с этим конкретным событием и соответственно - с его объектом. То есть имеет место жесткая фиксация связи между событием и теми обработчиками, которые должны выполниться при генерировании этого события.

Применительно к событиям введена следующая терминология. Объект, генерирующий ifiring) события, называют источником (source), а объект, получающий событие, называют приёмником (sink). Функции приёмника, реагирующие на событие, называют обработчиками (handlers) события.

Часто используются и другие термины. Объект, генерирующий события, называют издателем publisher). Говорят, что издатель публикует события, на которые должны подписаться подписчики (subscribers) - объекты, обработчики которых реагируют на события издателя. На событие указывает ссылка или дескриптор в объекте-издателе (объекте-источнике). Подписка на событие заключается в привязке к событию требуемого обработчика, то есть создание объекта делегата, инкапсулирующего обработчик объекта-подписчика (объекта-приёмника), и добавления этого делегата к объекту-событию издателя. Объект события представляет собой особый множественный объект делегата, который может вызываться только в объекте-издателе.

Важна роль событий при программировании .NET компонентов. Являясь .NET классом, компонент может быть очень простым или очень сложным. Компоненты могут функционировать параллельно с другими компонентами, взаимодействуя друг с другом посредством событий и образуя сложную многокомпонентную программную систему. Перед началом работы программной системы устанавливается связь между её компонентами, то есть осуществляется подписка компонентов-подписчиков на нужные им события конкретных компонентов-издателей. И только после завершения подписки компоненты начинают выполняться, передавать и получать события.

Заметим, что событие - это не просто факт свершения чего-либо. С событием обычно связывают объект с данными. Так что, получив событие, обработчик компонента-подписчика извлекает из этого объекта данных потребную информацию, которая может меняться с каждым новым появлением этого события.

После этого предварительного введения рассмотрим события подробнее.

Также как и в случае делегата, прежде чем объявлять событие, необходимо объявить делегат события. Делегат события определяет формат функции - обработчика события. Подписавшиеся на событие обработчики всех его подписчиков должна соответствовать этому формату, то есть иметь один и тот же список типов параметров и тип возвращаемого значения. Делегат события может быть объявлен вне класса объекта, если он требуется для классов других объектов или используется самостоятельно. Но можно объявить делегат события и в классе объекта, в котором будет генерироваться событие. Если событие важно и часто используется многими программистами, то для него создают свой собственный делегат и класс для объекта данных этого события. Например, для широко используемого события MouseDown нажатия на клавишу мыши создан делегат MouseEventHandler и класс MouseEventArgs для данных.

После объявления делегата события объявляется ссылка или дескриптор на событие:

//C#

event имя-делегата-события ссылка-на-событие;

//C++/CLI.

event имя-делегата-события ^ дескриптор-события;

где

  • event - ключевое слово, определяющее событие;

  • имя-делегата-события - имя делегата события, определяющего формат функций-обработчиков события;

  • ссылка-на-событие - имя ссылки на объект события, при свершении которого выполняются функции, инкапсулированные в объекте события;

  • дескриптор-события - имя управляемого указателя на объект события, при свершении которого выполняются функции, инкапсулированные в объекте события.

C#. В классе объекта-источника события объявляется открытая функция активизации, вызов которой генерирует событие:

public void имя-функции-активизации ()

{

if{ссылка-на-событие != null)

ссылка-на-событие (список-аргументов);

}

В функции активизации обязательно присутствует условный оператор, который только в том случае, когда объект события инициализирован функциями-обработчиками с помощью объектов делегата события, выполняет объект события - при этом выполняются все зарегистрированные функции-обработчики данного события и им передаётся список значений аргументов.

//C++/CLI

public: