泛型中的协方差:使用有界通配符创建泛型列表 [英] Covariance in Generics: Creating a Generic List with a Bounded Wildcard

查看:120
本文介绍了泛型中的协方差:使用有界通配符创建泛型列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking the whole day for a proper solution, bit I am fairly new to C#. If I am right, want something similar to the Java code

ArrayList<IAnimalStuff<? extends Animal>> ianimals = new ArrayList<>();

仅适用于C#。

详细场景:
我有一个基类(动物)和多个子类(例如Dog)。 / p>

Detailed Scenario: I have a base class (Animal) and multiple subclasses (e.g. Dog).

class Animal
{
}
class Dog : Animal
{
}

我创建了所有动物的通用列表,其中包含各种不同动物的对象

I create a common list of all animals, which contains objects of all kinds of different animals.

List<Animal> animals = new List<Animal>();
animals.add(new Dog()); // and so on

此外,对于每个由此衍生的特殊动物,我都有一个接口和一个类

Additionally, I have an interface and a class for each special animal derived from this interface.

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

public class DogStuff : IAnimalStuff<Dog>
{
    public override void doSomething(Dog animal) 
    {
    }
}

现在我想用Animals管理一个列表,用AnimalStuff管理一个列表。当遍历所有动物时,我要执行其他列表中对狗有效的所有Animalstuff。虽然动物列表没问题,但是创建另一个列表却很麻烦。

Now I want to manage one list with Animals and one list with AnimalStuff. When looping over all animals, I want to perform all Animalstuff in the other list which are valid for a dog. While a list of animals is no problem, I have my problems to create the other list.

List<IAnimalStuff<Animals>> ianimals = new List<IAnimalStuff<Animals>>();

与第一个列表不同,我只能向该类型的列表添加对象

Unlike in the first list, I only can add objects to this list of type

IAnimalStuff<Animals>

,但我也想这样做

ianimals.add(GetDogStuff()); // add object of type IAnimalStuff<Dog>

我认为这是有效的,因为Dog是Animal的子类。我认为使用Java代码的上一行可以解决此问题,但是我没有找到C#的任何解决方案。还是我走错了路?

I assumed this is valid, because Dog is a subclass of Animal. I think with the upper line of Java code this can be solved, but I did not find any solution for C#. Or am I on the wrong track?

推荐答案

C#具有声明站点差异,而不是像Java这样的使用站点差异。

C# has declaration-site variance, not use-site variance like Java.

在C#中,您可以执行以下操作:

In C# you could do this:

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

然后您可以说

IAnimalStuff<Mammal> iasm = new MammalStuff();
IAnimalStuff<Dog> iasd = iasm;

为什么这样做?因为 iasm.doSomething 会带走任何哺乳动物,而 iasd.doSomething 将只通过狗,而狗是哺乳动物。请注意,这是相反转换。

Why does this work? Because iasm.doSomething takes any mammal, and iasd.doSomething will be passed only dogs, and dogs are mammals. Notice that this is a contravariant conversion.

但是你不能走另一条路。您不能说狗是哺乳动物,所以狗是哺乳动物。那个哺乳动物的东西可以接受长颈鹿,但是狗的东西则不能。那将是协变转换。

But you cannot go the other way; you can't say "dog is a mammal, therefore a dogstuff is a mammalstuff". That mammalstuff can accept a giraffe, but a dogstuff cannot. That would be a covariant conversion.

这篇关于泛型中的协方差:使用有界通配符创建泛型列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆