HD86_ Ответов: 2

Как получить переменную коллекции элементов базового типа для хранения экземпляров коллекции элементов производного типа?


Collection<BaseType> CollectionBaseType;
Collection<DerivedType1> CollectionDerivedType1;
Collection<DerivedType2> CollectionDerivedType2;


Когда я объявляю коллекцию типа Collection & lt;basetype> и пытаюсь назначить ей экземпляр Collection<derivedtype1> или Collection<derivedtype2 & gt;, Я получаю ошибку компилятора. Это означает, что я не могу извлечь выгоду из наследования, когда имею дело с подобными коллекциями.

Есть ли способ, чтобы определить переменную, которая может содержать коллекция&ЛТ;базового типа&ГТ;, коллекция&ЛТ;derivedtype1&ГТ; или коллекция&ЛТ;derivedtype2&ГТ;?

Что я уже пробовал:

Collection<BaseType> CollectionBaseType;
Collection<DerivedType1> CollectionDerivedType1;
Collection<DerivedType2> CollectionDerivedType2;

2 Ответов

Рейтинг:
0

StM0n

Вы могли бы использовать object- но я думаю, это не то, чего ты хочешь достичь.

Невозможно перейти от базового типа к производному из-за того обстоятельства, что компилятор не может знать, какой тип вы ожидаете. Существует (по крайней мере) два возможных сценария развития событий.

CollectionDerivedType1 = CollectionBaseType;

Все объекты, которые не являются DerivedType1

1. вам обезательно
2. являются нулевыми

Если вы хотите фильтровать, вы можете использовать LINQ, если это то, чего вы хотите достичь.

Надеюсь, это поможет.


Рейтинг:
0

OriginalGriff

Проблема в том, что эти два списка не являются ковариантный:

Цитата:
В объектно-ориентированном программировании ковариантный возвращаемый тип метода-это тот, который может быть заменен" более узким " типом, когда метод переопределен в подклассе. Примечательным языком, в котором это довольно распространенная парадигма, является C++. C# не поддерживает ковариацию возвращаемого типа.
(Ковариантный тип возврата-Википедия[^])

Это в основном означает, что если вы создаете коллекции:
class Animal {...}
class Ape : Animal {...}
class Feline : Animal {...}

List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
List<Animal> animals = new List<Animal>();
Затем, поскольку обезьяна-это животное, вы можете добавить новый вид в любую коллекцию:
Ape newSpecies = new Ape("Pans Sapiens");
apes.Add(newSpecies);
animals.Add(newSpecies);
Но если вы попытаетесь добавить его к кошачьим:
cats.Add(newSpecies);
Вы получите ошибку компиляции:
Argument 1: cannot convert from 'GeneralTesting.frmMain.Ape' to 'GeneralTesting.frmMain.Feline'
Именно этого и следовало ожидать.
Но... если бы вы могли делать то, что хотите, вы могли бы сделать это:
Ape newSpecies = new Ape("Pans Sapiens");
animals = cats;
animals.Add(newSpecies);
И у вас будет обезьяна в вашей кошачьей коллекции - это означает, что ваше приложение рухнет позже, когда вы попытаетесь его использовать.

Вы можете добавить все элементы:
animals = new List<Animal>();
List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
...
animals.AddRange(apes);
animals.AddRange(cats);

Или даже явно:
animals = new List<Animal>();
List<Ape> apes = new List<Ape>();
List<Feline> cats = new List<Feline>();
...
animals.AddRange(apes.ConvertAll(x => (Animal)x));
animals.AddRange(cats.ConvertAll(x => (Animal)x));

Но вы не можете назначить элементы, которые не являются ковариантными.


StM0n

Ах ... ковариант-вот термин, который я искал. Черт, слишком стар, чтобы помнить :)

OriginalGriff

Существует слишком много специальных терминов, чтобы запомнить их все! :смеяться: