Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Троелсен Э. -> "С# и платформа .NET. Библиотека программиста" -> 102

С# и платформа .NET. Библиотека программиста - Троелсен Э.

Троелсен Э. С# и платформа .NET. Библиотека программиста — СПб.: Питер, 2004. — 796 c.
ISBN 5-318-00750-3
Скачать (прямая ссылка): cplatforma2004.pdf
Предыдущая << 1 .. 96 97 98 99 100 101 < 102 > 103 104 105 106 107 108 .. 320 >> Следующая

Il Меняем шины
g. ProcessCarst new Car. CarDel egate (RotateTi res));
return 0;
Обратите внимание, что два наших статических метода в точности совпадают с сигнатурой, определенной делегатом (они принимают один объекттипа Саг и возвращают значение типа void — то есть ничего не возвращают). Когда мы передаем делегату имя функции, тем самым это имя добавляется во внутренний список указателей на функции для делегата. То, что должно получиться при запуске нашей программы, представлено на рис. 5.5. Обратите внимание на те сообщения, которые генерируются при помощи свойств Target и Method.
|: J D;\CSharpBook..Labs\Chapter b\CarUelegate\bin\Debug\CarDelegate,eKe
¦нннш Calliny: Moid IJachCar <CtirDt: 1«^^еПрр.Саг> -->Target is a static MtJwd (Ліми inej a car
Ibis car is already clean___
Tbis car is already t: LDAtI. „ ,
C 1 влпintf a car
I Ik is с a* is a lr-e ail у u Ic an___
Calling: Uoid Rotate! ires <CarDr: lt?;jat еЛрр. Cu О *»к«*
— >Tai*yet is a static me (.hart Don * t need to he rotated... Don' t need to he rotated... T ires have been rotated Tires haue ln.it, rotated
Г ires have been rotated
i'r->: any Ui -'? t !> ґ пні І ти-
lit
Делегаты
241
M
Рис. 5.5. Применение делегата
Анализ работы делегата
В нашем примере работа программы начинается с создания экземпляра объекта класса Garage. Далее при помощи делегата этот объект передает всю работу двум статическим функциям. Таким образом, если мы пишем:
// Вымыть все грязные машины g.ProcessCarstnew Car.CarDelegate(WashCar)):
в действительности мы указываем: «Добавить указатель на функцию WashCarC) во внутреннюю таблицу указателей делегата CarDelegate и передать этот делегат функции Garage.ProcessCaru». Как и большинстве настоящих центров техобслуживания, реальную работу выполняет другая часть системы (которая потом будет объяс -нять нам, почему замена масла, на которую нужно было потратить тридцать минут, заняла два часа). Таким образом, функция ProcessCart) реально работает следующим образом:
.// CarDelegate уже указывает на функцию WashCarC) public void ProcessCarsfCar.CarDelegate proc)
foreachtCar с in the Cars": proc (с): /.' proc (с)
CarApp.WashCar(c)
}
To же самое можно сказать и в отношении второго метода:
// Поменять шины
g.ProcessCars(new Саг.CarDel egate(RotateTires)):
можно представить как
// Теперь CarDelegate указывает на функцию RotateTlres
public void PracessCarsCCar,CarDelegate proc) {
foreach(Car с in the Cars) proc(c): II procCc)
CarApp.RotateTiresCc)
242 Глава 5 • Дополнительные возможности классов С#
II Объединяем их в новый делегат, который теперь можно использовать где угодно HuIticastDelegate d = wash + rotate;
Обратите также внимание, что при вызове ProcessCars О мы обязаны создать и объект делегата при помощи ключевого слова new;
// Вымыть все грязные машины
g. ProcessCars(new Саг.CarDelegateCWashCar));
// Поменять шины
д.Proces sCa rs(new Саг.CarDel egate( RotateTi res)):
Если представлять себе делегат только как указатель на функцию, то это может показаться странным. Однако вспомним, что делегат — это на самом деле настоящий класс, производный от класса System.MulticastDelegats, и в этом свете создание нового объекта этого класса не должно вызывать удивления.
Многоадресносгь
Многоадресный делегат, как уже говорилось, — это объект, который может содержать в себе сразу несколько указателей на функции. В нашем примере мы не использовали такую возможность, а вместо этого два раза создавали делегат, каждый раз указывая лишь на одну функцию. Однако мы можем воспользоваться и много-адресностью:
// Добавляем во внутренний список указателей делегата сразу два указателя на функции:
public static int Main(string[] args)
{
Il Создаем объект Garage Garage g - newGarageu:
II Создаем два новых делегата
Car.CarDelegate wash = new Car.CarDelegate(WashCar):
Car.CarDelegate rotate - new Car.CarDelegate(RotateTires):
Il Чтобы объединить два указателя на функции в многоадресном делегате,
// используется перегруженный оператор сложения (+). В результате создается новый
// делегат, который содержит указатели на обе функции
g.ProcessCars(wash + rotate);
return G:
}
В этом примере вначале мы создали два отдельных делегата, каждый — с указателем на свою функцию. При вызове ProcessCarsC )этому методу в действительности передается новый делегат, который содержит все указатели на функции из двух прадыдущихделегатов. Оператор + — это просто более удобный вариант статического метода Delegate.CombineO (см. табл. 5.2). Таким образом, тот же самый код мог выглядеть следующим образом:
// Оператор + потно использовать вместо метода CombineO
g.ProcessCars((Car.CarDelegate)Delegate.Combine(wash, rotate)):
Если мы хотим, чтобы наш комбинированный делегат не исчез после выполнения метода ProcessCars а остался в боевой готовности для последующего использования, его можно создать за пределами ProcessCarsO:
// Создаем два новых делегата
Car.CarDelegate wash - new Car.CarDelegate(WashCar);
Предыдущая << 1 .. 96 97 98 99 100 101 < 102 > 103 104 105 106 107 108 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100