Когда мы говорим, что мы не можем преобразовать List<Fruit>
в List<Aliment>
, многое зависит от того, что мы подразумеваем под «преобразованием».
Если у вас есть List<Fruit>
и вы хотите List<Ailment>
, вы можете сделать это, создав новый список. Например, если fruitList
является List<Fruit>
:
var alimentList = new List<Aliment>(fruitList.Cast<Aliment>())
Поскольку каждый Fruit
является Aliment
, вы можете разыграть каждого из них как Aliment
и использовать их для заполнения нового List<Aliment>
.
Если вы это сделаете, ваш Fruits
конструктор скомпилирует:
public class Fruits : Aliments
{
public Fruits(List<Fruit> fruitList)
: base(new List<Aliment>(fruitList.Cast<Aliment>()))
{ }
}
То, что мы не можем сделать, это приведение a List<Fruit>
как List<Aliment>
.
Почему? Потому что, если бы мы могли, мы могли бы сделать это:
var alimentList = (List<Aliment>)fruitList;
alimentList.Add(new Vegetable());
Это не создаст новый список - он просто приведёт список к другому типу. Но если бы мы могли разыграть List<Fruit>
как List<Aliment>
, то мы могли бы добавить в список любой Aliment
, включая Vegetable
. Тогда у нас будет Vegetable
в нашем List<Fruit>
.
Это не всегда очевидно для нас, но компилятор сразу обнаруживает это и предотвращает.
Из-за этой проблемы, если вы используете код, который я показал выше, чтобы исправить ошибку в конструкторе, вы все равно столкнетесь с той же самой проблемой. Fruits
будет по-прежнему иметь свойство List<Aliment>
, которое наследуется от Aliments
, поэтому вы все равно можете сделать это:
var fruits = new Fruits(someListOfFruit);
fruits.AlimentList.Add(new Vegetable());
Это не даст вам ошибки компилятора, но, очевидно, это не то поведение, которое вам нужно.
Вам может помочь универсальный класс, подобный этому:
public abstract class Aliments<T> where T : Aliment
{
public Aliments(List<T> alimentList)
{
AlimentList = alimentList;
}
public List<T> AlimentList { get; private set; }
}
Это позволяет вам сделать это. Вы можете определить класс, который наследуется от Aliments
, но указывает фактический тип Aliment
.
public class Fruits : Aliments<Fruit>
{
public Fruits(List<Fruit> alimentList) : base(alimentList)
{
}
}
Указав Fruit
для универсального параметра T
, ваше свойство AlimentList
теперь определяется как List<Fruit>
. Компилятор только позволит вам добавить Fruit
к нему.