Глава 17.
делегаты
В этой главе рассказывается о чрезвычайно полезном механизме, который ис-
пользуется уже много лет и называется функциями обратного вызова. В Microsoft
.NET Framework этот механизм поддерживается при помощи
делегатов
(delegates).
В отличие от других платформ, например неуправляемого языка C++, делегаты
обладают более широкой функциональностью. Например, они обеспечивают
безопасность типов при выполнении обратного вызова (способствуя решению
одной из важнейших задач CLR). Кроме того, они обеспечивают возможность по-
следовательного вызова нескольких методов, а также вызова как статических, так
и экземплярных методов.
знакомство с делегатами
Функция
qsort
исполняющей среды C получает указатель на функцию обратного
вызова для сортировки элементов массивов. В Windows механизм обратного вы-
зова используется оконными процедурами, процедурами перехвата, асинхронным
вызовом процедур и др. В .NET Framework методы обратного вызова также имеют
многочисленные применения. К примеру, можно зарегистрировать такой метод для
получения различных уведомлений: о необработанных исключениях, изменении
состояния окон, выборе пунктов меню, изменениях файловой системы и заверше-
нии асинхронных операций.
В неуправляемом языке C/C++ адрес функции — не более чем адрес в памяти,
не несущий дополнительной информации. В нем не содержится информация ни
о количестве ожидаемых функцией параметров, ни об их типе, ни о типе возвра-
щаемого функцией значения, ни о правилах вызова. Другими словами, функции
обратного вызова C/C++ не обеспечивают безопасность типов (хотя их и отличает
высокая скорость выполнения).
В .NET Framework функции обратного вызова играют не менее важную роль, чем
при неуправляемом программировании для Windows. Однако данная платформа
предоставляет в распоряжение разработчика
делегатов
— механизм, безопасный по
отношению к типам. Рассмотрим пример объявления, создания и использования
делегатов:
using System;
using System.Windows.Forms;
using System.IO;
// Объявление делегата; экземпляр ссылается на метод
435
Знакомство.с.делегатами
// с параметром типа Int32, возвращающий значение void
internal delegate void Feedback(Int32 value);
public sealed class Program {
public static void Main() {
StaticDelegateDemo();
InstanceDelegateDemo();
ChainDelegateDemo1(new Program());
ChainDelegateDemo2(new Program());
}
private static void StaticDelegateDemo() {
Console.WriteLine("----- Static Delegate Demo -----");
Counter(1, 3, null);
Counter(1, 3, new Feedback(Program.FeedbackToConsole));
Counter(1, 3, new Feedback(FeedbackToMsgBox)); // Префикс "Program."
// не обязателен
Console.WriteLine();
}
private static void InstanceDelegateDemo() {
Console.WriteLine("----- Instance Delegate Demo -----");
Program p = new Program();
Counter(1, 3, new Feedback(p.FeedbackToFile));
Console.WriteLine();
}
private static void ChainDelegateDemo1(Program p) {
Console.WriteLine("----- Chain Delegate Demo 1 -----");
Feedback fb1 = new Feedback(FeedbackToConsole);
Feedback fb2 = new Feedback(FeedbackToMsgBox);
Feedback fb3 = new Feedback(p.FeedbackToFile);
Feedback fbChain = null;
fbChain = (Feedback) Delegate.Combine(fbChain, fb1);
fbChain = (Feedback) Delegate.Combine(fbChain, fb2);
fbChain = (Feedback) Delegate.Combine(fbChain, fb3);
Counter(1, 2, fbChain);
Console.WriteLine();
fbChain = (Feedback)
Delegate.Remove(fbChain, new Feedback(FeedbackToMsgBox));
Counter(1, 2, fbChain);
}
private static void ChainDelegateDemo2(Program p) {
Console.WriteLine("----- Chain Delegate Demo 2 -----");
Feedback fb1 = new Feedback(FeedbackToConsole);
Feedback fb2 = new Feedback(FeedbackToMsgBox);
Feedback fb3 = new Feedback(p.FeedbackToFile);
Feedback fbChain = null;
продолжение
436
Do'stlaringiz bilan baham: |