c# - 我可以调用一个采用 IEnumerable<Baseclass<superclass>> 和 IEnumerable<Derivedclass<subclass>> 的方法吗

标签 c# .net 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);
        }
    }
}

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

IList<SpecializedCatVet<Cat>>IEnumerable<Vet<Animal>>不可能。怎么会这样?在此之前,它们是非泛型的,我还有一些其他问题,因为我无法覆盖 vert 接口(interface)的 takeCareOf 方法。我原以为 Animal 的 IEnumerable 可以很容易地用 Dog 列表实例化,解析泛型集合的情况也是如此,只要它们的类型参数是所需类型的派生。但事实并非如此,我似乎无法弄清楚为什么,或者如何正确地做到这一点。

感谢阅读。

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

最佳答案

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

var cat = new Cat();

treatSickAnimal(DogVets, cat);

本质上是试图强制狗 vert 治疗猫。

您可以通过使您的方法对动物参数具有通用性来解决这个问题:

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

这应该允许您的代码正确编译并确保您不会试图强制任何狗 vert 治疗猫。


旁注 - 除非您计划拥有 DogCat 的专门类型(子类)以及专用于这些子类的 vert ,否则您可以简化定义SpecializedDogVetSpecializedCatVet 是这样的:

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

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

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

public IList<SpecializedCatVet> CatVets = new List<SpecializedCatVet>();
public IList<SpecializedDogVet> DogVets = new List<SpecializedDogVet>();

关于c# - 我可以调用一个采用 IEnumerable<Baseclass<superclass>> 和 IEnumerable<Derivedclass<subclass>> 的方法吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50963586/

相关文章:

c# - 如何将 XmlElementAttribute 用于 List<T>?

c# - 防止在设计时调整高度控件的大小

C# 阻止组合框 selectionChanged 事件调用自身

oop - 什么是成员与属性

c# - 调用动态类型对象的泛型方法

c# - 如何匹配区分大小写的用户名和密码

.net - {version} 值如何填充到 BundleConfig 文件中?

c# - C#中如何在非静态方法中调用静态方法

Javascript 以函数风格创建对象

ios - UITableView 的属性可以是 UITableView Delegate 和 DataSource