我可以使用IEnumerable <Derivedclass <subclass >>调用一个采用IEnumerable <Baseclass <superclass >>的方法吗?

ras*_*s91 2 .net c# oop .net-core

我有一些相当于此的代码(虽然这是一个简化):

namespace AnimalHospital
{
    public class Animal { }
    public class Dog : Animal { }
    public class Cat : Animal { }

    public interface Vet<T> where T : Animal 
    { 
        void takeCareOf(T animal); 
    }
    public abstract class SpecializedDogVet<T> : Vet<T> where T : Dog
    {
       public abstract void takeCareOf(T dog); 
    }

    public abstract class SpecializedCatVet<T> : Vet<T> where T : Cat
    {
        public abstract void takeCareOf(T cat);
    }

    public class AnimalHospital
    {
        public IList<SpecializedCatVet<Cat>> CatVets = new List<SpecializedCatVet<Cat>>();
        public IList<SpecializedDogVet<Dog>> DogVets = new List<SpecializedDogVet<Dog>>();

        private void treatSickAnimal(IEnumerable<Vet<Animal>> vets, Animal patient)
        {
            foreach(var vet in vets)
            {
                vet.takeCareOf(patient);
            }
        }

        public void treatSickCat(Cat cat)
        {
            treatSickAnimal(CatVets, cat);
        }

        public void treatSickDog(Dog dog)
        {
            treatSickAnimal(DogVets, dog);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到错误,告诉我转换自:

IList<SpecializedCatVet<Cat>>IEnumerable<Vet<Animal>>是不可能的.怎么会这样?在此之前他们是非通用的,我有一些其他问题,因为我无法覆盖vet接口takeCareOf方法.我曾预料到,由于动态的IEnumerable可以很容易地用Dog列表进行实例化,因此只要类型参数是所需类型的派生,解析泛型集合的情况就是如此.但事实并非如此,我似乎无法弄清楚为什么或如何正确地做到这一点.

谢谢阅读.

更新:我接受JLRishe的回答,很有道理.非常感谢你.

JLR*_*she 6

这是不允许的,因为如果它被允许,你可以这样:

var cat = new Cat();

treatSickAnimal(DogVets, cat);
Run Code Online (Sandbox Code Playgroud)

并且基本上试图强迫狗兽医治疗猫.

您可以通过在dynamic参数上使用方法通用来解决此问题:

private void treatSickAnimal<T>(IEnumerable<Vet<T>> vets, T patient) where T : Animal
{
    foreach (var vet in vets)
    {
        vet.takeCareOf(patient);
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该允许你的代码正确编译,并确保你不要试图强迫任何狗兽医治疗猫.


旁注 - 除非您计划使用专门用于这些子类的Dog和/ Cat和专门的类型(子类),否则您可以简化定义,SpecializedDogVet并且SpecializedCatVet如下所示:

public abstract class SpecializedDogVet : Vet<Dog>
{
    public abstract void takeCareOf(Dog dog);
}

public abstract class SpecializedCatVet : Vet<Cat>
{
    public abstract void takeCareOf(Cat cat);
}
Run Code Online (Sandbox Code Playgroud)

然后你会引用这样的类型:

public IList<SpecializedCatVet> CatVets = new List<SpecializedCatVet>();
public IList<SpecializedDogVet> DogVets = new List<SpecializedDogVet>();
Run Code Online (Sandbox Code Playgroud)