我有这个代码示例。我不知道它为什么不编译。它不允许从D
转换为A<B>
。
D
继承A<C>
。 C
继承了B
,这意味着我应该能够将D
传递给A<B>
方法论证吗?我可能在这里遗漏了一些明显的东西。
using System.Collections.Generic;
public class Program
{
public void Main()
{
var d = new D();
Foo(d); //Cannot convert D to A<B>
}
private void Foo(A<B> bar)
{
}
}
public abstract class A<TypeB> where TypeB : B
{
public abstract List<TypeB> list { get; set; }
}
public abstract class B
{
}
public class C : B
{
}
public class D : A<C>
{
public override List<C> list { get; set; }
}
答案 0 :(得分:9)
这个问题已在本网站上被问过数百次。
假设你有一碗水果。是一碗苹果吗?苹果是一种水果,为什么一碗水果不是一碗苹果?显然是因为一碗水果已经含有香蕉,所以不是一碗苹果。
假设你有一碗苹果。这是一碗水果吗?你想说'苹果是一种水果,因此一碗苹果就是一碗水果&#34;。但这是错误的。 一碗水果是你可以放入香蕉的东西,因为有一个手术你可以在一碗水果上进行,你不能在一碗苹果上做,一碗苹果不能用于预期一碗水果的环境中。
您想要的转换类型的技术名称是&#34;泛型协变转换&#34;。 C#仅在少数特定情况下支持通用协变转换:
IEnumerable<T>
。您可以在期望IEnumerable<Apple>
的上下文中使用IEnumerable<Fruit>
,因为无法将香蕉放入IEnumerable<Fruit>
。但是你不能将你的A<Apple>
类用作A<Fruit>
,因为编译器不相信你已经阻止了另一种类型Banana的可能性,它扩展了Fruit只能接受一个只能接受Apple的方法。 / p>
在本网站上搜索&#34;协方差和逆变&#34;你会发现很多关于此的问题。