我想添加不同类型的对象,这些对象派生自具有泛型的一个类到基类型列表.我得到这个编译错误
Error 2 Argument 1: cannot convert from 'ConsoleApplication1.Stable' to 'ConsoleApplication1.ShelterBase<ConsoleApplication1.AnimalBase>' C:\Users\ysn\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs 43 26 ConsoleApplication1
我看不到这个问题,你能为我提供另一种做这种事情的方法吗?
abstract class AnimalBase { public int SomeCommonProperty;} abstract class ShelterBase<T> where T : AnimalBase { public abstract List<T> GetAnimals(); public abstract void FeedAnimals(List<T> animals); } class Horse : AnimalBase { } class Stable : ShelterBase<Horse> { public override List<Horse> GetAnimals() { return new List<Horse>(); } public override void FeedAnimals(List<Horse> animals) { // Feed them } } class Duck : AnimalBase { } class HenHouse : ShelterBase<Duck> { public override List<Duck> GetAnimals() { return new List<Duck>(); } public override void FeedAnimals(List<Duck> animals) { // Feed them } } class Program { static void Main(string[] args) { List<ShelterBase<AnimalBase>> shelters = new List<ShelterBase<AnimalBase>>(); ///////////////////////////// following two lines do not compile shelters.Add(new Stable()); shelters.Add(new HenHouse()); ///////////////////////////// foreach (var shelter in shelters) { var animals = shelter.GetAnimals(); // do sth with 'animals' collection } } }
解决方法
您可以使用
contravariance,但只有当您将抽象类更改为接口,并将GetAnimals的返回类型更改为IEnumerable< T>,因为List< T>不支持此功能.
工作原理:
abstract class AnimalBase { public int SomeCommonProperty;} interface IShelterBase<out T> where T : AnimalBase { IEnumerable<T> GetAnimals(); } class Horse : AnimalBase { } class Stable : IShelterBase<Horse> { public IEnumerable<Horse> GetAnimals() { return new List<Horse>(); } } class Duck : AnimalBase { } class HenHouse : IShelterBase<Duck> { public IEnumerable<Duck> GetAnimals() { return new List<Duck>(); } } void Main() { List<IShelterBase<AnimalBase>> shelters = new List<IShelterBase<AnimalBase>>(); shelters.Add(new Stable()); shelters.Add(new HenHouse()); foreach (var shelter in shelters) { var animals = shelter.GetAnimals(); // do something with 'animals' collection } }