Обобщения ( шаблоны ) Лекция 5
Тип, метод или интерфейс параметризованный другим типом Обобщенный тип Тип ( класс, структура ), который параметризован другим типом class Queue { } struct Complex { } Обобщенная функция Функция, параметром которой является тип T Swap (T x, T y) { } Обобщенный делегат Делегат, параметрами которого являются типы delegate T MyDelegate () where T : new() Обобщенный интерфейс interface IEnumerable { }
Не типизированные коллекции Один код для всех Нет контроля типов, накладные расходы Коллекции с жёстко заданным типом Каждый раз новый код Контроль типов, нет накладных расходов Обобщенные коллекции Один код для всех Контроль типов, нет накладных расходов
[Модификаторы] class Имя Класса [Ограничения типов] {…} Обозначения Типов := Обозначение 1 [,ОбозначениеN] Ограничения типов := where Обозначениe Типа 1 : ограничения [, Обозначениe ТипаN : ограниченияN] Пример : public class Stack T where T : IDisposable, new() { T T[] arr; TT T top = default(T); TT T example = new T(); T Stack(int size) { arr = new T[size]; } T void Push(T item) {…} T T Pop() {return arr[i]; } void Dispose() {top.Dispose();} } Создание объекта обобщенного типа : Необходимо указать все типы - параметры Stack myIntStack = new Stack (); Dictionary myDict = new Dictionary ();
Типов - параметров может быть много Обозначения типов – любые ( допустимые ) имена Обозначения типов могут использоваться в коде как обычный тип Для задания значения по умолчанию используется синтаксис Тип Переменная = default( Тип ); class MyDictionary where TKey : Complex, IComparable where TValue : class { } struct MyGenericStruct { } class MyGenericClass { C c = dafault(C); }
[ Модификаторы ] Возвращаемый Тип Имя Метода ( параметры ) [ Ограничения типов ] { } Примеры : void Swap (ref T a, ref T b) { T c = a; b = a; a = c; } public T Swap (T a, U b, Complex comp) {…} public T Copy (T a, T b) where T : new() { T result = new T(); …..} Использование : При вызове необходимо задать все типы параметры, если компилятор не может определить их из контекста Swap (ref comp1, ref comp2); int I = Swap (intVariable, longVariable, myIntComplexVariable);
[Модификаторы] interface Имя Интерфейса [Ограничения типов] {…} Пример : public interface MyInterface { T GetT(K k); K GerK(T t); T propertyT { get; } T propretyK { get; set; } bool Equal(T t, K k); } Использование : При реализации, либо класс должен быть обобщенным, либо должен реализовывать конкретный тип обобщенного интерфейса class MyClass : MyInterface { } class MyClass1 : MyInterface { } class MyClass2 : MyInterface { }
Типы - параметры : если что - то явно не оговорено, то этого НЕТ ! По умолчанию доступны только методы object Если нужны дополнительные методы Необходимо использовать ограничения
Интерфейсы where T : ICloneable, IDisposable Базовый класс where T : MyBaseClass Ссылочные типы / Типы значения where T : struct where T : class Нельзя одновременно указать и class, и struct Наличие конструктора по умолчанию ограничение должно быть последним в списке where T : new()
Нельзя требовать наличие операции Дублируйте обычными методами Нельзя требовать конструктора с параметрами Если указано несколько ограничений Все должны выполняться одновременно Если нужна альтернатива – используйте базовые интерфейсы
Обобщения и ограничения
Реализуйте Стек Стек должен быть обобщенным типом Методы void Push(T); T Pop(); T Top(); int Count(); В основном классе создайте обобщенный метод, создающий и заполняющий стек некоторым количеством объектов со значениями по умолчанию Создайте код для тестирования вашего стека Потребуйте от типа T, чтобы он реализовывал ICloneable и реализуйте T Top() так, чтобы он возвращал копию объекта, а не сам объект