Вход/Регистрация
ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
вернуться

Троелсен Эндрю

Шрифт:

cl.OnAboutToBlow(new Car.AboutToBlow(CarAboutToBlow));

cl.OnExploded(new Car.Exploded(CarExploded));

// Ускоряемся (при этом генерируются события) .

Console.WriteLine("\n***** Ускорение *****");

for(int i = 0; i ‹ 6; i++) cl.Accelerate(20);

Console.ReadLine;

 }

 // Car будет вызывать эти методы.

 public static void CarAboutToBlow(string msg) {Console.WriteLine(msg);}

 public static void CarExploded(string msg) {Console.WriteLine(msg);}

}

Здесь следует отметить только то, вызывающая сторона задает значения членам-переменным делегата с помощью вспомогательных методов регистрации. Кроме того, поскольку делегаты AboutToBlow и Exploded вложены в класс Car, при их размещении следует использовать полные имена (например, Car.AboutToBlow). Как любому конструктору, мы передаем конструктору делегата имя метода, который нужно добавить в список вызовов. В данном случае это два статических члена класса Program (если вложить указанные методы в новый класс, это будет очень похоже на тип CarEventSink из примера Event Interface).

Реализация групповых вызовов

Напомним, что делегаты .NET наделены возможностью группового вызова. Другими словами, объект делегата может поддерживать не один метод, а целый список доступных для вызова методов. Когда требуется добавить в объект делегата несколько методов, используется перегруженная операция +=, а не прямое присваивание. Чтобы разрешить групповой вызов для типа Car, можно обновить методы OnAboutToBlow и OnExploded так, как показано ниже.

public class Car {

 // Добавление элемента в список вызовов.

 public void OnAboutToBlow(AboutToBlow clientMethod) {almostDeadList += clientMethod;}

 public void OnExploded(Exploded clientMethod) {explodedList += clientMethod;}

 …

}

Теперь вызывающая сторона может зарегистрировать несколько целевых объектов.

class Program {

 static void Main(string[] args) {

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

// Регистрация множества обработчиков событий.

c1.OnAboutToBlow(new Car.AboutToBlow(CarAboutToBlow));

c1.OnAboutToBlow(new Car.AboutToBlow(CarlsAlmostDoomed));

c1.OnExploded(new Car.Exploded(CarExploded));

…

 }

 // Car будет вызывать эти методы.

 public static void CarAboutToBlow(string msg) {Console.WriteLine (msg);}

 public static void CarIsAlmostDoomed(string msg) {Console.WriteLine("Важное сообщение от Car: {0}", msg);}

 public static void CarExploded(string msg) {Console.WriteLine(msg);}

}

В программном воде CIL операция += преобразуется в вызов статического метода Delegate.Combine (можно было бы вызвать Delegate.Combine непосредственно, но операция += предлагает более простую альтернативу). Взгляните, например, на CIL-представление метода OnAboutToBlow.

.method public hidebysig instance void OnAboutToBlow (class CarDelegate.Car/AboutToBlow clientMethod) cil managed {

 .maxstack 8

 ldarg.0

 dup

 ldfld class CarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList

 ldarg.1

 call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)

 castclass CarDelegate.Car/AboutToBlow

 stfld class СarDelegate.Car/AboutToBlow CarDelegate.Car::almostDeadList

 ret

}

Класс Delegate определяет также статический метод Remove, который позволит вызывающей стороне динамически удалять элементы из списка вызовов. Легко догадаться, что в C# разработчики могут для этого использовать перегруженную операцию -=. Чтобы предоставить вызывающей стороне возможность не привязываться к обозначениям AboutToBlow и Exploded, можно добавить в тип Car следующие вспомогательные методы (обратите внимание на операцию -=).

  • Читать дальше
  • 1
  • ...
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: