С учетом того, что очень многие специальные делегаты принимают экземпляр object в первом параметре и экземпляр производного от EventArgs класса во втором, предыдущий пример можно дополнительно упростить за счет применения обобщенного типа EventHandler, где Т — специальный тип, производный от EventArgs. Рассмотрим следующую модификацию типа Car (обратите внимание, что определять специальный тип делегата больше не нужно):

public class Car

{

...

  public event EventHandler Exploded;

  public event EventHandler AboutToBlow;

}

Затем в вызывающем коде тип EventHandler можно использовать везде, где ранее указывался CarEngineHandler (или снова применять групповое преобразование методов):

Console.WriteLine("***** Prim and Proper Events *****\n");

// Создать объект Car обычным образом.

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

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

c1.AboutToBlow += CarIsAlmostDoomed;

c1.AboutToBlow += CarAboutToBlow;

EventHandler d = CarExploded;

c1.Exploded += d;

...

Итак, к настоящему моменту вы узнали основные аспекты работы с делегатами и событиями в С#. Хотя этого вполне достаточно для решения практически любых задач, связанных с обратными вызовами, в завершение главы мы рассмотрим несколько финальных упрощений, в частности анонимные методы и лямбда-выражения.

<p id="AutBody_Root463">Понятие анонимных методов C#</p>

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

SomeType t = new SomeType();

// Предположим, что SomeDeletage может указывать на методы,

// которые не принимают аргументов и возвращают void.

t.SomeEvent += new SomeDelegate(MyEventHandler);

// Обычно вызывается только объектом SomeDelegate.

static void MyEventHandler()

{

  // Делать что-нибудь при возникновении события.

}

Однако если подумать, то такие методы, как MyEventHandler(), редко предназначены для вызова из любой другой части программы кроме делегата. С точки зрения продуктивности вручную определять отдельный метод для вызова объектом делегата несколько хлопотно (хотя и вполне допустимо).

Для решения указанной проблемы событие можно ассоциировать прямо с блоком операторов кода во время регистрации события. Формально такой код называется анонимным методом. Чтобы ознакомиться с синтаксисом, создайте новый проект консольного приложения по имени AnonymousMethods, после чего скопируйте в него файлы Car.cs и CarEventArgs.cs из проекта CarEvents (не забыв изменить пространство имен на AnonymousMethods). Модифицируйте код в файле Program.cs, как показано ниже, для обработки событий, посылаемых из класса Car, с использованием анонимных методов вместо специальных именованных обработчиков событий:

using System;

using AnonymousMethods;

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

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

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

c1.AboutToBlow += delegate

{

  Console.WriteLine("Eek! Going too fast!");

};

c1.AboutToBlow += delegate(object sender, CarEventArgs e)

{

  Console.WriteLine("Message from Car: {0}", e.msg);

};

c1.Exploded += delegate(object sender, CarEventArgs e)

{

  Console.WriteLine("Fatal Message from Car: {0}", e.msg);

};

// В конце концов, этот код будет инициировать события.

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

{

  c1.Accelerate(20);

}

Console.ReadLine();

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

Перейти на страницу:

Похожие книги