Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# - лекции IntUit (Биллиг В.А.).pdf
Скачиваний:
140
Добавлен:
13.02.2015
Размер:
4.13 Mб
Скачать

случае успеха создается новый экземпляр делегата, который и связывается с функцией.

Покажем, что и сам функциональный тип-делегат можно объявлять с родовыми параметрами. Вот пример такого объявления:

public delegate T FunTwoArg<T>(T a, T b);

Добавим в наш тестовый пример код, демонстрирующий работу с этим делегатом:

FunTwoArg<int> mydel; mydel = max2;

max = mydel(17, 21); Console.WriteLine("max= {0}", max);

Вот как выглядят результаты работы тестового примера:

Рис. 22.7. Результаты работы с универсальными делегатами

Универсальные делегаты с успехом используются при определении событий. В частности, класс EventHandler, применяемый для всех событий, не имеющих собственных аргументов, теперь дополнен универсальным аналогом, определенным следующим образом:

public void delegate EventHandler<T> (object sender, T args) where T:EventArgs

Этот делегат может применяться и для событий с собственными аргументами, поскольку вместо параметра TT может быть подставлен конкретный тип - потомок класса EventArgs, дополненный нужными аргументами.

Framework .Net и универсальность

Универсальность принадлежит к основным механизмам языка. Ее введение в язык C# не могло не сказаться на всех его основных свойствах. Как уже говорилось, классы и все частные случаи стали обладать этим свойством. Введение универсальности не должно было ухудшить уже достигнутые свойства языка - статический контроль типов, динамическое связывание и полиморфизм. Не должна была пострадать и эффективность выполнения программ, использующих универсальные классы.

Решение этих задач потребовало введения универсальности не только в язык C#, но и поддержки на уровне каркаса Framework .Net и языка IL, включающем теперь параметризованные типы. Универсальный класс C# не является шаблоном, на основе которого строится конкретизированный класс, компилируемый далее в класс (тип) IL. Компилятору языка C# нет необходимости создавать классы для каждой конкретизации типов универсального класса. Вместо этого происходит компиляция универсального класса C# в параметризованный тип IL. Когда же CLR занимается исполнением управляемого кода, то вся необходимая информация о конкретных типах извлекается из метаданных, сопровождающих объекты.

При этом дублирования кода не происходит и на уровне JIT-компиляторов, которые, однажды сгенерировав код для конкретного типа, сохраняют ссылку на этот участок кода и передают ее, когда такой код понадобится вторично. Это справедливо как для ссылочных, так и значимых типов.

Естественно, что универсальность потребовала введения в библиотеку FCL соответствующих классов, интерфейсов, делегатов и методов классов, обладающих этим свойством.

Так, например, в класс System.Array добавлен ряд универсальных статических методов. Вот один из них:

public static int BinarySearch<T>(T[] array, T value);

В таблице 22.1 показаны некоторые универсальные классы и интерфейсы библиотеки FCL 2.0 из пространства имен System.Collections.Generic и их аналоги из пространства System.Collections.

Таблица 22.1. Соответствие между универсальными классами и их обычными двойниками

 

Универсальный класс

 

Обычный

Универсальный

Обычный

 

 

класс

интерфейс

интерфейс

 

 

 

 

 

 

 

 

 

Comparer<T>

 

Comparer

ICollection<T>

ICollection

 

 

 

 

 

 

Dictionary<K,T>

 

HashTable

IComparable<T>

IComparable

 

 

 

 

 

 

LinkedList<T>

 

----

IDictionary<K,T>

IDictionary

 

 

 

 

 

 

List<T>

 

ArrayList

IEnumerable<T>

IEnumerable

 

 

 

 

 

 

Queue<T>

 

Queue

IEnumerator<T>

IEnumerator

 

 

 

 

 

 

SortedDictionary<K,T>

 

SortedList

IList<T>

IList

 

 

 

 

 

 

Stack<T>

 

Stack

 

 

 

 

 

 

 

 

Сериализация и универсализация также согласуются друг с другом, так что можно иметь универсальный класс, для которого задан атрибут сериализации.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]