Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

new Car.CarEngineHandler(OnCarEngineEvent));

// Увеличить скорость (это инициирует события).

Console.WriteLine("***** Speeding up *****");

for (int i = 0; i < 6; i++)

{

c1.Accelerate(20);

}

Console.ReadLine;

// Цель для входящих сообщений.

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 = 30

CurrentSpeed = 50

CurrentSpeed = 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

{

// Добавление поддержки группового вызова.

// Обратите внимание на использование операции +=,

// а не обычной операции присваивания (=).

public void RegisterWithCarEngine(

CarEngineHandler methodToCall)

{

_listOfHandlers += methodToCall;

}

...

}

Когда операция

+=
используется с объектом делегата, компилятор преобразует ее в вызов статического метода
Delegate.Combine
. На самом деле можно было бы вызывать
Delegate.Combine
напрямую, однако операция
+=
предлагает более простую альтернативу. Хотя нет никакой необходимости в модификации текущего метода
RegisterWithCarEngine
, ниже представлен пример применения
Delegate.Combine
вместо операции
+=
:

public void RegisterWithCarEngine( CarEngineHandler methodToCall )

{

if (_listOfHandlers == null)

{

_listOfHandlers = methodToCall;

}

else

{

_listOfHandlers =

Delegate.Combine(_listOfHandlers, methodToCall)

as CarEngineHandler;

}

}

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

Console.WriteLine("***** Delegates as event enablers *****\n");

// Создать объект Car.

Car c1 = new Car("SlugBug", 100, 10);

// Зарегистрировать несколько обработчиков событий.

c1.RegisterWithCarEngine(

new Car.CarEngineHandler(OnCarEngineEvent));

c1.RegisterWithCarEngine(

new Car.CarEngineHandler(OnCarEngineEvent2));

// Увеличить скорость (это инициирует события).

Console.WriteLine("***** Speeding up *****");

for (int i = 0; i < 6; i++)

{

c1.Accelerate(20);

}

Console.ReadLine;

// Теперь есть ДВА метода, которые будут

// вызываться Car при отправке уведомлений.

static void OnCarEngineEvent(string msg)

{

Console.WriteLine("\n*** Message From Car Object ***");

Console.WriteLine("=> {0}", msg);

Console.WriteLine("*********************************\n");

}

static void OnCarEngineEvent2(string msg)

{

Console.WriteLine("=> {0}", msg.ToUpper);

}

Удаление целей из списка вызовов делегата

В классе

Delegate
также определен статический метод
Remove
, который позволяет вызывающему коду динамически удалять отдельные методы из списка вызовов объекта делегата. В итоге у вызывающего кода появляется возможность легко "отменять подписку" на заданное уведомление во время выполнения. Хотя метод
Delegate.Remove
допускается вызывать в коде напрямую, разработчики C# могут использовать в качестве удобного сокращения операцию
– =
. Давайте добавим в класс
Car
новый метод, который позволяет вызывающему коду исключать метод из списка вызовов:

Поделиться с друзьями: