Вы не можете разыграть List<ClassThatImplementsInterface>
как List<IInterfaceItImplements>
.
Если бы вы могли, и вы сделали это:
var classList = new List<ClassThatImplementsInterface>();
var interfaceList = (List<IInterfaceItImplements>)classList;
... тогда вы сможете сделатьthis:
interfaceList.Add(new SomeOtherClassThatImplementsTheInterface);
Но приведение списка не создает новый список.В приведенном выше примере нет двух списков.Есть две переменные со ссылками на один и тот же список.Если бы вы могли приводить, как показано выше, вы могли бы определить список одного типа и добавить к нему совершенно другой тип.Компилятор предотвращает это.
Вы можете
- создать новый
List<IDemoInterface>
и добавить к нему элементы.(Или массив, IEnumerable и т. Д.) - Оставьте список как есть и просто разыгрывайте отдельные элементы, когда / если вам нужно.В большинстве случаев нам не нужно приводить что-либо как интерфейс, который он реализует.
Если нам нужно привести целую коллекцию как другой тип, это скорее всего потому, что мы передаем это в качестве аргумента.,
Это действительно хорошая причина , а не , чтобы определять аргумент метода как тип коллекции, такой как List<T>
, который может быть изменен, если только мы не намерены изменять коллекцию.
Это одна из причин, по которой мы передаем менее специфичные типы коллекций, например IEnumerable<T>
.
Предположим, что аргумент метода выглядит следующим образом:
void MethodINeedToPassTheArgumentTo(IEnumerable<IDemoInterface> items)
Теперь мы можем взятьнаши List<TestClass>
и сделайте это:
MethodINeedToPassTheArgumentTo(testClassList.Cast<IDemoInterface>);
Мы не создаем новую коллекцию.Мы передаем ссылку, которая позволяет другому методу просматривать элементы в списке, каждый в отдельности , приведенный к IDemoInterface
.Для практических целей выглядит для другого метода как коллекция IDemoInterface
, и это нормально, потому что другой элемент не может изменить коллекцию.Он не может пытаться добавить другие типы в List<TestClass>
.