Язык программирования C#9 и платформа .NET5
} // end of method Car::add_AboutToBlowКак и можно было ожидать, метод
будет вызыватьremove_AboutToBlow():Delegate.Remove()public hidebysig specialname instance void remove_AboutToBlow (class [System.Runtime]System.EventHandler`1<class CarEvents.CarEventArgs> 'value') cilmanaged{...IL_000b: call class [System.Runtime]System.Delegate[System.Runtime]System.Delegate::Remove(class [System.Runtime]System.Delegate,class [System.Runtime]System.Delegate)...}Наконец, в коде CIL, представляющем само событие, используются директивы
и.addonдля отображения на имена корректных методов.removeonиadd_XXX(), подлежащих вызову:remove_XXX().event class [System.Runtime]System.EventHandler`1<class CarEvents.CarEventArgs> AboutToBlow{.addon instance void CarEvents.Car::add_AboutToBlow(class [System.Runtime]System.EventHandler`1<class CarEvents.CarEventArgs>).removeon instance void CarEvents.Car::remove_AboutToBlow(class [System.Runtime]System.EventHandler`1<class CarEvents.CarEventArgs>)} // end of event Car::AboutToBlowТеперь, когда вы понимаете, каким образом строить класс, способный отправлять события C# (и знаете, что события — всего лишь способ сэкономить время на наборе кода), следующий крупный вопрос связан с организацией прослушивания входящих событий на стороне вызывающего кода.
Прослушивание входящих событий
События C# также упрощают действие по регистрации обработчиков событий на стороне вызывающего кода. Вместо того чтобы указывать специальные вспомогательные методы, вызывающий код просто применяет операции
и+=напрямую (что приводит к внутренним вызовам методов-=илиadd_XXX()). При регистрации события руководствуйтесь показанным ниже шаблоном:remove_XXX()// ИмяОбъекта.ИмяСобытия +=// new СвязанныйДелегат(функцияДляВызова);Car.CarEngineHandler d =new Car.CarEngineHandler(CarExplodedEventHandler);myCar.Exploded += d;Отключить от источника событий можно с помощью операции
в соответствии со следующим шаблоном:-=// ИмяОбъекта.ИмяСобытия - =// СвязанныйДелегат(функцияДляВызова);myCar.Exploded -= d;Кроме того, с событиями можно использовать синтаксис группового преобразования методов:
Car.CarEngineHandler d = CarExplodedEventHandler;myCar.Exploded += d;При наличии таких весьма предсказуемых шаблонов переделайте вызывающий код, применив на этот раз синтаксис регистрации событий С#:
Console.WriteLine("***** Fun with Events *****\n");Car c1 = new Car("SlugBug", 100, 10);// Зарегистрировать обработчики событий.c1.AboutToBlow += CarIsAlmostDoomed;c1.AboutToBlow += CarAboutToBlow;Car.CarEngineHandler d = CarExploded;c1.Exploded += d;Console.WriteLine("***** Speeding up *****");for (int i = 0; i < 6; i++){c1.Accelerate(20);}// Удалить метод CarExploded() из списка вызовов.c1.Exploded -= d;Console.WriteLine("\n***** Speeding up *****");for (int i = 0; i < 6; i++){c1.Accelerate(20);}Console.ReadLine();static void CarAboutToBlow(string msg){Console.WriteLine(msg);}static void CarIsAlmostDoomed(string msg){Console.WriteLine("=> Critical Message from Car: {0}", msg);}static void CarExploded(string msg){Console.WriteLine(msg);}Упрощение регистрации событий с использованием Visual Studio
Среда Visual Studio предлагает помощь в процессе регистрации обработчиков событий. В случае применения синтаксиса
при регистрации событий открывается окно IntelliSense, приглашающее нажать клавишу <ТаЬ> для автоматического завершения связанного экземпляра делегата (рис. 12.1), что достигается с использованием синтаксиса групповых преобразований методов.+=