C# 泛型中的协方差:使用有界通配符创建泛型列表

C# 泛型中的协方差:使用有界通配符创建泛型列表,c#,generics,inheritance,covariance,C#,Generics,Inheritance,Covariance,我整天都在寻找一个合适的解决方案,但我对C#还相当陌生。 如果我是对的,我想要一些类似于Java代码的东西 ArrayList<IAnimalStuff<? extends Animal>> ianimals = new ArrayList<>(); 我创建了一个所有动物的通用列表,其中包含各种不同动物的对象 List<Animal> animals = new List<Animal>(); animals.add(new Dog(

我整天都在寻找一个合适的解决方案,但我对C#还相当陌生。 如果我是对的,我想要一些类似于Java代码的东西

ArrayList<IAnimalStuff<? extends Animal>> ianimals = new ArrayList<>();
我创建了一个所有动物的通用列表,其中包含各种不同动物的对象

List<Animal> animals = new List<Animal>();
animals.add(new Dog()); // and so on
列出动物=新建列表();
动物。添加(新狗());//等等
此外,我还有一个接口和一个类,用于从该接口派生的每个特殊动物

interface IAnimalStuff<TAnimal> where TAnimal : Animal
{
    void doSomething(TAnimal animal);
}

public class DogStuff : IAnimalStuff<Dog>
{
    public override void doSomething(Dog animal) 
    {
    }
}
界面IAnimalStuff,其中TAnimal:动物 { 无效剂量(动物); } 公共类狗东西:IAnimalStuff { 公共药物(狗和动物) { } } 现在我想管理一个动物列表和一个动物列表。当循环遍历所有动物时,我想执行其他列表中对狗有效的所有Animalstuff。虽然动物列表没有问题,但我在创建另一个列表时遇到了问题

List<IAnimalStuff<Animals>> ianimals = new List<IAnimalStuff<Animals>>();
List ianimals=new List();
与第一个列表不同,我只能将对象添加到此类型列表中

IAnimalStuff<Animals>
IAnimalStuff
,但我也想做

ianimals.add(GetDogStuff()); // add object of type IAnimalStuff<Dog>
ianimals.add(GetDogStuff());//添加IAnimalStuff类型的对象
我认为这是正确的,因为狗是动物的一个亚类。我认为使用Java代码的上行链路可以解决这个问题,但我没有找到任何C#的解决方案。还是我走错了路?

C#有声明站点差异,而不是像Java那样使用站点差异

在C#中,您可以这样做:

interface IAnimalStuff<in TAnimal> where TAnimal : Animal // note "in"
{
    void doSomething(TAnimal animal);
}
接口IAnimalStuff,其中TAnimal:Animal//注意“in”
{
无效剂量(动物);
}
然后你可以说

IAnimalStuff<Mammal> iasm = new MammalStuff();
IAnimalStuff<Dog> iasd = iasm;
IAnimalStuff iasm=new stuff();
IAnimalStuff iasd=iasm;
为什么这样做有效?因为
iasm.doSomething
接受任何哺乳动物,
iasd.doSomething
将只传递给狗,而狗是哺乳动物。请注意,这是一个逆变转换


但你不能走另一条路;你不能说“狗是哺乳动物,所以狗是哺乳动物”。这种哺乳动物可以接受长颈鹿,但狗不能。这将是一个协变转换。

我认为问题可能在于您对列表的声明:

List<IAnimalStuff<Animals>> ianimals = new List<IAnimalStuff<Animals>>();
List ianimals=new List();
这是将动物凝灰岩的“动物”铸造成“动物”类型。
相反,尝试使用接口作为基础
IAnimal
,并将集合定义为
IAnimalStuff
。然后让
Dog
IAnimal
继承,它应该可以完成你想要的。

不清楚你是否真的读过c#中的协方差?你似乎有合适的术语来查找信息,但实际上在你的问题中没有提到它。。。你是否只需要链接到像这样的文章,或者你已经尝试过了,但没有成功?我也找到了你提到的文章,但我没有帮助我。据我所知,我的方法应该是可行的。也许我再也看不见树木了。C#没有使用站点差异,只是声明站点差异。谢谢你的解释。我进一步阅读了使用站点差异和声明站点差异。我想要的(我认为)仍然是协方差转换。拥有IAnimalStuff的列表,并添加各种动物,例如IAnimalStuff。据我所知,这应该是可能的,没有通用修饰符。不幸的是,只有当我的泛型接口只有返回类型为T的对象的方法,但不使用类型为T的对象时,这才可能实现,事实并非如此。所以我想,我有一些设计问题。但还是非常感谢你。
List<IAnimalStuff<Animals>> ianimals = new List<IAnimalStuff<Animals>>();