Одним из ограничивающих аспектов использования универсальных типов является то, что универсальные типы не так гибки в преобразованиях типов, как традиционные типы.List<Object>
не совместимо с присвоением с List<String>
или любым другим типом объекта.
В Linq есть вспомогательные функции преобразования, такие как .Cast<T>()
, которые будут логически преобразовывать каждый элемент из одного списка в тип T для формирования нового списка типа List<T>
.Хотя вспомогательная функция удобна, она не меняет того факта, что List<N>
не совместима по типу с List<T>
, даже если N и T каким-то образом совместимы по типу.
По сути, универсальныйтипы не являются полиморфными. Не существует общего типа между экземплярами одного и того же универсального типа - ни один тип, с которым вы можете объявить переменную, может содержать List<T>
и List<N>
.
Если вы создаете свой собственный универсальный тип и хотите иметь какой-то общий тип, который можно использовать для переноса всех проявлений универсального типа, вам нужно выполнить некоторую гимнастику типов, чтобы заставить его работать,и вы будете ограничены в том, что вы можете сделать.Вам нужно определить базовый класс или тип интерфейса, а затем вам нужно сделать так, чтобы ваш универсальный тип наследовал от базового класса или реализовал тип интерфейса.В этой конфигурации вы можете объявить переменную с типом базового класса или типом интерфейса и назначить MyClass<N>
и MyClass<T>
одной и той же переменной, получая доступ только к членам, определенным в базовом классе (которые, конечно, не будут иметь никакихзнание параметров типа N или T).
Параметры ковариантного типа (IMyInterface<out T>
) могут помочь вам в этом, но ковариация накладывает серьезные ограничения на то, что вы можете делать в этом интерфейсе - ковариантный тип Tможет использоваться только для результатов функции, но не для аргументов или настраиваемых свойств.
Простой факт, что IList<T>
не объявлен ковариантным, не является случайностью или недосмотром - он не может быть ковариантным.Чтобы быть полезным IList<T>
нужны такие методы, как Add (T item) и Remove (T item), которые запрещены, когда T ковариантен.