Язык программирования C#9 и платформа .NET5
Часть 238 из 642 Информация о книге
{/// Если этот автомобиль сломан, то отправить сообщение об этом.if (_carIsDead){_listOfHandlers?.Invoke("Sorry, this car is dead...");}else{CurrentSpeed += delta;// Автомобиль почти сломан?if (10 == (MaxSpeed - CurrentSpeed)){_listOfHandlers?.Invoke("Careful buddy! Gonna blow!");}if (CurrentSpeed >= MaxSpeed){_carIsDead = true;}else{Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed);}}}Обратите внимание, что при попытке вызова методов, поддерживаемых переменной-членом
, используется синтаксис распространения_listOfHandlers. Причина в том, что создание таких объектов посредством вызова вспомогательного методаnullявляется задачей вызывающего кода. Если вызывающий код не вызывалRegisterWithCarEngine(), а мы попытаемся обратиться к списку вызовов делегата, то получим исключениеRegisterWithCarEngine()во время выполнения. Теперь, когда инфраструктура делегатов готова, внесите в файлNullReferenceExceptionследующие изменения:Program.csusing System;using CarDelegate;Console.WriteLine("** Delegates as event enablers **\n");<b>// Создать объект Car.</b>Car c1 = new Car("SlugBug", 100, 10);<b>// Сообщить объекту Car, какой метод вызывать,</b><b>// когда он пожелает отправить сообщение.</b>c1.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent));<b>// Увеличить скорость (это инициирует события).</b>Console.WriteLine("***** Speeding up *****");for (int i = 0; i < 6; i++){c1.Accelerate(20);}Console.ReadLine();<b>// Цель для входящих сообщений.</b>static void OnCarEngineEvent(string msg){Console.WriteLine("\n*** Message From Car Object ***");Console.WriteLine("=> {0}", msg);Console.WriteLine("********************\n");}Код начинается с создания нового объекта
. Поскольку вас интересуют события, связанные с двигателем, следующий шаг заключается в вызове специальной регистрационной функцииCar. Вспомните, что методRegisterWithCarEngine()ожидает получения экземпляра вложенного делегатаRegisterWithCarEngine(), и как в случае любого делегата, в параметре конструктора передается метод, на который он должен указывать. Трюк здесь в том, что интересующий метод находится в классеCarEngineHandler! Обратите также внимание, что методProgramполностью соответствует связанному делегату, потому что принимаетOnCarEngineEvent()и возвращаетstring. Ниже показан вывод приведенного примера:void***** Delegates as event enablers ********** Speeding up *****CurrentSpeed = 30CurrentSpeed = 50CurrentSpeed = 70***** Message From Car Object *****=> Careful buddy! Gonna blow!***********************************CurrentSpeed = 90***** Message From Car Object *****=> Sorry, this car is dead...***********************************Включение группового вызова
Вспомните, что делегаты .NET Core обладают встроенной возможностью группового вызова. Другими словами, объект делегата может поддерживать целый список методов для вызова, а не просто единственный метод. Для добавления нескольких методов к объекту делегата вместо прямого присваивания применяется перегруженная операция
. Чтобы включить групповой вызов в классе+=, можно модифицировать методCar:RegisterWithCarEngine()public class Car{<b> // Добавление поддержки группового вызова.</b><b> // Обратите внимание на использование операции +=,</b><b> // а не обычной операции присваивания (=).</b>public void RegisterWithCarEngine(CarEngineHandler methodToCall)