// 'традиционного' синтаксиса делегата.
MyDelegate d = new MyDelegate(MyTarget) d("Дополнительные строковые данные");
// Регистрация цели с помощью
// группового преобразования метода.
MyDelegate d2 = MyTarget;
d2(9); // Проблема объектного образа.
…
}
// Ввиду отсутствия типовой безопасности мы должны
// определить соответствующий тип до преобразования.
static void MyTarget(object arg) {
if (arg is int) {
int i = (int)arg; // Проблема восстановления значения.
Console.WriteLine("++arg: {0}", ++i);
}
if (arg is string) {
string s
Console.WriteLine("arg в верхнем регистре: {0}", s.ToUpper);
}
}
}
Когда вы посылаете целевому объекту тип, характеризуемый значением, это значение (конечно же) "упаковывается" в объект и "распаковывается" после его получения целевым методом. Точно так же, поскольку поступающий параметр может быть всем чем угодно, вы должны динамически проверить соответствующий тип перед тем, как выполнить преобразование. С помощью обобщенных делегатов вы можете получить всю необходимую гибкость без "проблем".
Несколько слов о вложенных делегатах
Завершим эту главу рассмотрением еще одного аспекта обобщенных делегатов. Вы знаете, что делегаты могут быть вложены в тип класса, что должно означать тесную ассоциацию между этими двумя ссылочными типами. Если тип-контейнер при этом оказывается обобщенным, вложенный делегат может использовать в своем определении параметры типа.
// Вложенные обобщающе делегаты могут иметь доступ к параметрам
// обобщенного типа-контейнера.
public class MyList‹T› {
private List‹T› listOfData = new List‹T›;
public delegate void ListDelegate(T arg);
}
Исходный код. Проект GenericDetegate размещен в подкаталоге, соответствующем главе 10.
Резюме
Обобщения можно обоснованно считать главным из усовершенствований, предложенных в C# 2005. Как вы могли убедиться, обобщенный элемент позволяет указать "заполнители" (т.е. параметры типа), которые конкретизируются в момент создания типа (или вызова, в случае обобщенных методов). По сути, обобщения дают решение проблем объектных образов и типовой безопасности, усложняющих разработку программ в среде .NET 1.1.
Чаще всего вы будете просто использовать обобщенные типы, предлагаемые библиотеками базовых классов .NET, но можно создавать и свои собственные обобщенные типы. При создании обобщенных типов можно указать любое число ограничений, чтобы повысить уровень типовой безопасности и гарантировать, что соответствующие операции будут выполняться с "известными величинами".
ЧАСТЬ III. Программирование компоновочных блоков .NET
ГЛАВА 11. Компоновочные блоки .NET
Любое из приложений, описанных в этой книге в предыдущих десяти главах, было обычным "автономным" приложением, вся программная логика которого целиком содержались в одном выполняемом файле (*.exe). Однако одной из главных задач платформы .NET является
Сначала мы рассмотрим различия между одномодульными и многомодульными компоновочными блоками, а также между "приватными" и "общедоступными" компоновочными блоками. Затем мы выясним, как среда, выполнений .NET определяет параметры размещения компоновочного блока, и попытаемся понять роль GAC (Global Assembly Cache – глобальный кэш компоновочных блоков), файлов конфигурации приложения (файлы *.config), политики публикации компоновочных блоков и пространства имен System.Configuration.
Роль компоновочных блоков .NET