Увы, ограничения обобщенных типов при использовании операций в C# 2005 не поддерживаются.
Исходный код. Проект CustomGenericCollection размещен в подкаталоге, соответствующем главе 10.
Создание обобщенных базовых классов
Перед рассмотрением обобщенных интерфейсов следует указать на то, что обобщенные классы могут быть базовыми для других классов и могут таким образом определять любое число виртуальных и абстрактных методов. Однако производные типы должны подчиняться определенным правилам, вытекающим из природы обобщенной абстракции. Во-первых, если обобщенный класс расширяется необобщенным, то производный класс должен конкретизировать параметр типа,
// Предположим, что создан пользовательский
// обобщенный класс списка.
public class MyList‹T› {
private List‹T› listOfData = new List‹T›;
}
// Конкретные типы должны указать параметр типа,
// если они получаются из обобщенного базового класса.
public class MyStringList: MyList‹string› {}
Кроме того, если обобщенный базовый класс определяет обобщенные виртуальные или абстрактные методы, производный тип должен переопределить эти обобщенные методы, используя конкретизированный параметр типа.
// Обобщенный класс с виртуальным методом.
public class MyList‹T› {
private List‹T› listOfData = new List‹T›;
public virtual void PrintList(T data) {}
}
public class MyStringList: MyList‹string› {
// В производных методах нужно заменить параметр типа,
// используемый а родительском классе.
public override void PrintList(string data) {}
}
Если производный тип тоже является обобщенным, дочерний класс может (опционально) использовать заменитель типа в своем определении. Однако знайте, что любые ограничения, размещенные в базовом классе, должны "учитываться" и производным типом. Например:
// Обратите внимание, теперь здесь имеется ограничение,
// требующее конструктор по умолчанию.
public class MyList‹T› where T: new {
private List‹T› listOfData = new List‹T›;
public virtual void PrintList(T data) {}
// Производный тип должен учитывать ограничения базового.
public class MyReadOnlyList‹T›: MyList‹T› where T: new {
public override void PrintList(T data) {}
}
Если вы только не планируете построить свою собственную библиотеку обобщений
Создание обобщенных интерфейсов
Вы уже видели при рассмотрении пространства имен System.Collections. Generiс, что обобщенные интерфейсы в C# также допустимы (например, IEnumerable‹Т›). Вы, конечно, можете определить свои собственные обобщенные интерфейсы (как с ограничениями, так и без ограничений). Предположим, что нужно определить интерфейс, который сможет выполнять бинарные операции с параметрами обобщенного типа.
public interface IBinaryOperations‹T› {
T Add(T arg1, T arg2);
T Subtract(T arg1, T arg2);
T Multiply(T arg1, T arg2);
T Divide(T arg1, T arg2);
}
Известно, что интерфейсы остаются почти бесполезными, пока они не реализованы некоторым классом или структурой. При реализации обобщенного интерфейса поддерживающий его тип указывает тип заполнителя.
public class BasicMath: IBinaryOperations‹int› {
public int Add(int arg1, int arg2) { return arg1 + arg2; }
public int Subtract(int arg1, int arg2) { return arg1 – arg2; }
public int Multiply(int arg1, int arg2) { return arg1 * arg2; }
public int Divide(int arg1, int arg2) { return arg1 / arg2; }
}
После этого вы можете использовать BasicMath, как и ожидали.
static void Main(string[] args) {