Чтобы решить эту конкретную проблему, вам на самом деле не нужна ковариация.Когда вы используете списки животных, вы все равно получаете интерфейс AnimalBase
через IShelterBase<out T>
.Можно также выставить список AnimalBase
через базовый класс.
Лучше и чище будет сделать GetAnimals
, возвращающий список AnimalBase
, и создать перегрузку в каждом классе укрытиячтобы вернуть список этого конкретного животного.
abstract class ShelterBase<T> where T : AnimalBase
{
public List<AnimalBase> GetAnimals(){return new List<AnimalBase>();}
}
class Stable : ShelterBase<Horse>
{
public List<Horse> GetHorses(){return new List<Horse>();}
}
Еще одна проблема с этим дизайном - выставить коллекцию через самый производный тип - то есть List
, в отличие от IEnumerable
или IList
.Поскольку вы столкнулись с проблемой создания класса, абстрагирующего коллекцию животных, вы должны действительно защитить внутреннюю коллекцию, запретив прямую вставку / удаление.Как только вы это сделаете, все станет немного проще.Например, вот как я бы решил эту проблему.
abstract class ShelterBase<T> where T : AnimalBase
{
protected List<T> _Animals;
public AnimalBase() {
_Animals = CreateAnimalCollection();
}
protected abstract List<T> CreateAnimalCollection();
public IEnumerable<AnimalBase> GetAnimals(){return _Animals.Cast<AnimalBase>();}
//Add remove operations go here
public void Add(T animal){_Animals.Add(animal);}
public void Remove(T animal){_Animals.Remove(animal);}
}
class Stable : ShelterBase<Horse>
{
protected override List<Horse> CreateAnimalCollection(){return new List<Horse>();}
public IEnumerable<Horse> GetHorses(){return _Animals;}
}
Вы заметите, что внутренняя коллекция животных никогда не отображается в виде изменяемого списка.Это хорошо, так как позволяет вам лучше контролировать его содержимое.Методы Add
и Remove
в базовом укрытии в этом примере немного надуманы, так как они не добавляют ничего лишнего по сравнению с прямым доступом к сбору, но вы можете добавить туда логику - например, проверку максимального размера укрытия при добавлении или проверкевозраст животных до его удаления.