|
Программирование >> Обработка исключительных ситуаций
Листинг 10.7. Оповещение наблюдателей с помощью событий using System; namespace ConsoleApplicationl { public delegate void DelO; class Subj public event Del Oops; public void CryOopsO Console.WriteLineC OOPS! ); if ( Oops != null ) OopsO: объявление делегата класс-источник объявление события метод, инициирующий событие class ObsA класс-наблюдатель public void DoO; реакция на событие источника Console.WriteLineC Вижу, что OOPS! ); class ObsB public static void SeeO класс-наблюдатель реакция на событие источника Console.WriteLineC Я тоже вижу, что OOPS! ) class Classl static void MainO { Subj s = new Subj(); ObsA ol = new ObsAC): ObsA o2 = new ObsAC); s.Oops += new DelC ol.Do ); s.Oops += new DelC o2.Do ); s.Oops += new DelC ObsB.See ); s. CryOopsO; объект класса-источника объекты класса-наблюдателя добавление обработчиков к событию инициирование события Внешний код может работать с событиями единственным образом: добавлять обработчики в список или удалять их, поскольку вне класса могут использоваться только операции += и -=. Тип результата этих операций - void, в отличие от операций сложного присваивания для арифметических типов. Иного способа доступа к списку обработчиков нет. Внутри класса, в котором описано событие, с ним можно обращаться, как с обгч-ным полем, имеющим тип делегата: использовать операции отношения, присваивания и т. д. Значение события по умолчанию - null. Например, в методе CryOops выполняется проверка на nul 1 для того, чтобы избежать генерации исключения System.Nul1ReferenceException. В библиотеке .NET описано огромное количество стандартных делегатов, предназначенных для реализации механизма обработки событий. Большинство этих классов оформлено по одним и тем же правилам: имя делегата заканчивается суффиксом EventHandler; делегат получает два параметра: О первый параметр задает источник события и имеет тип object; О второй параметр задает аргументы события и имеет тип EventArgs или производный от него. Если обработчикам события требуется специфическая информация о событии, то для этого создают класс, производный от стандартного класса EventArgs, и добавляют в него необходимую информацию. Если делегат не использует такую информацию, можно не описывать делегата и собственный тип аргументов, а обойтись стандартным классом делегата System.EventHandler. Имя обработчика события принято составлять из префикса On и имени события. В листинге 10.8 приведен пример из листинга 10.7, оформленный в соответствии со стандартными соглашениями .NET. Найдите восемь отличий! Листинг 10.8. Использование стандартного делегата EventHandler using System; namespace ConsoleApplicationi class Subj { public event EventHandler Oops; public void CryOops() Console.WriteLineC OOPS! ); if ( Oops != null ) OopsC this, null ); class ObsA s.CryOopsO: Те, кто работает с С# версии 2.0, могут упростить эту программу, используя новую возможность неявного создания делегатов при регистрации обработчиков событий. Соответствующий вариант приведен в листинге 10.9. В демонстрационных целях в код добавлен новый анонимный обработчик - еще один механизм, появившийся в новой версии языка. Листинг 10.9. Использование делегатов и анонимных методов (версия 2.0) using System; namespace ConsoleApplicationl class Subj public event EventHandler Oops; public void CryOopsO Console.WriteLineC OOPS! ) Листинг 10.8 (продолжение) public void OnOopsC object sender. EventArgs e ) { Console.WriteLineC Вижу, что OOPS! ); class ObsB public static void OnOopsC object sender, EventArgs e ) Console.WriteLineC Я тоже вижу, что OOPS! ): class Classl { static void MainO Subj s = new SubjC); ObsA ol = new ObsAC); ObsA o2 = new ObsAC); s.Oops += new EventHandlerC ol.OnOops ): s.Oops += new EventHandlerC o2.0nOops ): s.Oops +- new EventHandlerC ObsB.OnOops );
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |