c# - 泛型中的协方差 : Creating a Generic List with a Bounded Wildcard

标签 c# generics inheritance covariance

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

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

仅适用于 C#。或者当我走错路时的另一种解决方案。

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

class Animal
{
}
class Dog : Animal
{
}

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

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

此外,我有一个接口(interface)和一个从该接口(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。虽然动物列表没问题,但我在创建另一个列表时遇到了问题。

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

与第一个列表不同,我只能将对象添加到此类型的列表中

IAnimalStuff<Animals>

不过我也想做

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

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

最佳答案

C# 具有声明位置差异,而不是像 Java 那样的使用位置差异。

在 C# 中你可以这样做:

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 将只传递给狗,而狗是哺乳动物。请注意,这是一个逆变 转换。

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

关于c# - 泛型中的协方差 : Creating a Generic List with a Bounded Wildcard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46893858/

相关文章:

Java匿名泛型继承

Java多态指针

java - 如何使用 JNI 实例化 Java 泛型?

java - 跨 2 个类共享数据

c# - NLog 不显示任何内容?

c# - 如何在 Windows Phone 7Thi 中从 Web 服务检索多个图像

C#按原样获取一个tcp数据包数据

c# - IList<Type> 到 IList<BaseType>

python - 我如何在python中将相同的列表对象分配给两个不同的变量名?

c# - 无法抑制 Rider 中的 CA1307 警告