Вход/Регистрация
Полное руководство. С# 4.0
вернуться

Шилдт Герберт

Шрифт:

При запуске события вызывается метод OnSomeEvent. В этом методе происходит циклическое обращение к элементам массива evnt для вызова по очереди каждого об работчика событий.

Как демонстрирует рассматриваемый здесь пример программы, механизм хранения обработчиков событий нетрудно реализовать, если в этом есть потребность. Но для боль шинства приложений более подходящим оказывается используемый по умолчанию ме ханизм хранения обработчиков событий, который обеспечивает форма оператора event без аксессоров. Тем не менее аксессорная форма оператора event используется в особых случаях. Так, если обработчики событий необходимо выполнять в программе в порядке их приоритетности, а не в том порядке, в каком они вводятся в цепочку событий, то для их хранения можно воспользоваться очередью по приоритету.

ПРИМЕЧАНИЕ В многопоточных приложениях обычно приходится синхронизировать доступ к аксессо рам событий. Подробнее о многопоточном программировании речь пойдет в главе 23. Разнообразные возможности событий

События могут быть определены и в интерфейсах. При этом события должны предоставляться классами, реализующими интерфейсы. События могут быть также определены как абстрактные (abstract). В этом случае конкретное событие должно быть реализовано в производном классе. Но аксессорные формы событий не могут быть абстрактными. Кроме того, событие может быть определено как герметичное (sealed). И наконец, событие может быть виртуальным, т.е. его можно переопреде лить в производном классе. Применение анонимных методов и лямбда-выражений вместе с событиями

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

Как упоминалось выше, лямбда-выражениям теперь отдается большее предпо чтение по сравнению с анонимными методами, поэтому начнем именно с них. Ниже приведен пример программы, в которой лямбда-выражение используется в качестве обработчика событий. // Использовать лямбда-выражение в качестве обработчика событий. using System; // Объявить тип делегата для события. delegate void MyEventHandler (int n); // Объявить класс, содержащий событие. class MyEvent { public event MyEventHandler SomeEvent; // Этот метод вызывается для запуска события. public void OnSomeEvent(int n) { if (SomeEvent != null) SomeEvent(n); } } class LambdaEventDemo { static void Main { MyEvent evt = new MyEvent; // Использовать лямбда-выражение в качестве обработчика событий. evt.SomeEvent += (n) => Console.WriteLine("Событие получено. Значение равно " + n); // Запустить событие. evt.OnSomeEvent(1); evt.OnSomeEvent(2); } }

Вот к какому результату приводит выполнение этой программы. Событие получено. Значение равно 1 Событие получено. Значение равно 2

Обратите особое внимание на то, как в этой программе лямбда-выражение исполь зуется в качестве обработчика событий. evt.SomeEvent += (n) => Console.WriteLine("Событие получено. Значение равно " + n);

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

Несмотря на то что при создании анонимной функции предпочтение следует теперь отдавать лямбда-выражениям, в качестве обработчика событий можно по- прежнему использовать анонимный метод. Ниже приведен вариант обработчика со бытий из предыдущего примера, измененный с целью продемонстрировать примене ние анонимного метода. // Использовать анонимный метод в качестве обработчика событий. evt.SomeEvent += delegate(int n) { Console.WriteLine("Событие получено. Значение равно " + n); };

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

В C# разрешается формировать какие угодно разновидности событий. Но ради со вместимости программных компонентов со средой .NET Framework следует придер живаться рекомендаций, установленных для этой цели корпорацией Microsoft. Эти рекомендации, по существу, сводятся к следующему требованию: у обработчиков со бытий должны быть два параметра. Первый из них — ссылка на объект, формирую щий событие, второй — параметр типа EventArgs, содержащий любую дополнитель ную информацию о событии, которая требуется обработчику. Таким образом, .NET- совместимые обработчики событий должны иметь следующую общую форму. void обработчик(object отправитель, EventArgs е) { // ... }

Как правило, отправитель — это параметр, передаваемый вызывающим кодом с помощью ключевого слова this. А параметр е типа EventArgs содержит дополни тельную информацию о событии и может быть проигнорирован, если он не нужен. Сам класс EventArgs не содержит поля, которые могут быть использованы для передачи дополнительных данных обработчику. Напротив, EventArgs служит в ка честве базового класса, от которого получается производньгй класс, содержащий все необходимые поля. Тем не менее в классе EventArgs имеется одно поле Empty типа static, которое представляет собой объект типа EventArgs без данных. Ниже приведен пример программы, в которой формируется .NET-совместимое событие. // Пример формирования .NET-совместимого события. using System; // Объявить класс, производный от класса EventArgs. class MyEventArgs : EventArgs { public int EventNum; } // Объявить тип делегата для события. delegate void MyEventHandler(object source, MyEventArgs arg); // Объявить класс, содержащий событие. class MyEvent { static int count = 0; public event MyEventHandler SomeEvent; // Этот метод запускает событие SomeEvent. public void OnSomeEvent { MyEventArgs arg = new MyEventArgs; if(SomeEvent != null) { arg.EventNum = count++; SomeEvent(this, arg); } } } class X { public void Handler(object source, MyEventArgs arg) { Console.WriteLine("Событие " + arg.EventNum + " получено объектом класса X."); Console.WriteLine("Источник: " + source); Console.WriteLine; } } class Y { public void Handler(object source, MyEventArgs arg) { Console.WriteLine("Событие " + arg.EventNum + " получено объектом класса Y."); Console.WriteLine("Источник: " + source); Console.WriteLine; } } class EventDemo6 { static void Main { X ob1 = new X; Y ob2 = new Y; MyEvent evt = new MyEvent; // Добавить обработчик Handler в цепочку событий. evt.SomeEvent += ob1.Handler; evt.SomeEvent += ob2.Handler; // Запустить событие. evt.OnSomeEvent; evt.OnSomeEvent; } }

Ниже приведен результат выполнения этой программы. Событие 0 получено объектом класса X Источник: MyEvent Событие 0 получено объектом класса Y Источник: MyEvent Событие 1 получено объектом класса X Источник: MyEvent Событие 1 получено объектом класса Y Источник: MyEvent

В данном примере создается класс MyEventArgs, производный от класса EventArgs. В классе MyEventArgs добавляется лишь одно его собственное поле: EventNum. Затем объявляется делегат MyEventHandler, принимающий два параметра, требующиеся для среды .NET Framework. Как пояснялось выше, первый параметр содержит ссыл ку на объект, формирующий событие, а второй параметр — ссылку на объект класса EventArgs или производного от него класса. Обработчики событий Handler, опре деляемые в классах X и Y, принимают параметры тех же самых типов.

  • Читать дальше
  • 1
  • ...
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: