theCars.Add(new Car("BillyBob", 100, 0, false, true));
}
}
Класс Garage будет определять общедоступный метод ProcessCars, который в качестве единственного аргумента получит новый тип делегата (Car.CarDelegate). В ProcessCars каждый объект Car из коллекции будет передаваться в виде параметра "той функции, на которую указывает" делегат. При этом ProcessCars использует члены Target и Method из System.MulticastDelegate, чтобы определить, на какую из функций делегат указывает в настоящий момент.
// Класс Garage имеет метод, использующий CarDelegate.
using System.Collections;
…
public class Garage {
…
// Этот метод получает Car.CarDelegate в виде параметра.
public void ProcessCars(Car.CarDelegate proc) {
// Куда направить вызов?
Console.WriteLine("***** Вызывается: {0} *****", proc.Method)
// Вызывается метод экземпляра или статический метод?
if (proc.Target
else Console.WriteLine("-›Целевым является статический метод");
// Вызов "указанного" метода всех машин по очереди.
foreach (Car с in theCars) {
Console.
proc(c);
}
}
}
Как и в случае любого делегата, при вызове ProcessCars мы должны указать имя метода, который обработает запрос. Напомним, что такой метод может быть или статическим, или методом экземпляра. Для примера предположим, что в качестве такого метода будут использоваться члены экземпляра нового класса ServiceDepartment (отдел технического обслуживании), которым назначены имела WashCar и RotateTires. Обратите внимание на то, что эти два метода используют новые свойства Rotate и Dirty типа Car.
// Этот класс определяет методы, которые будут вызываться
// типом Car.CarDelegate.
public class ServiceDepartment {
public void WashCar(Car c) {
if (c.Dirty) Console.WriteLine("Моем машину");
else Console.WriteLine("Эта машина уже помыта…");
}
public void RotateTires(Car с) {
if (c.Rotate) Console.WriteLine("Меняем шины");
else Console.WriteLine("Менять шины не требуется…");
}
}
Теперь проиллюстрируем взаимодействие между новыми типами Car, CarDelegate, Garage и ServiceDepartment, рассмотрев их использование в следующем фрагменте программного кода.
// Garage направляет все заказы в ServiceDepartment
// (найти хорошего механика всегда проблема…)
public class Program {
static void Main(string[] args) {
// Создание гаража.
Garage g = new Garage;
// Создание отделения обслуживания,
ServiceDepartment sd = new ServiceDepartment;
// Garage моет машины и меняет шины,
// делегируя соответствующие полномочия ServiceDepartment.
g.ProcessCars(new Car.CarDelegate(sd.WashCar));
g.ProcessCars(new Car.CarDelegate(sd.RotateTires));
Console.ReadLine;
}
}
На рис. 8.6 показан соответствующий вывод.
Рис. 8.6. Перекладывание ответственности
Анализ программного кода делегирования
Предложенный выше метод Main начинается с создания экземпляров типов Garage и ServiceDepartment. Когда вы пишете
// Помыть все грязные машины.
g.ProcessCars(new Car.CarDelegate(sd.WashCar));
это на самом деле означает: "Добавить указатель на метод ServiceDepartment.WashCar к объекту Car.CarDelegate и передать этот объект в Garage.ProcessCars". Подобно любому автомобильному предприятию в реальном мире, все заказы передаются в отдел технического обслуживания (что и объясняет, почему замена масла, обычно требующая 30 минут, занимает целых 2 часа). С учетом этого ProcessCars можно интерпретировать так.