这个问题似乎没有任何问题,所以我会编出几个问题来回答。
什么是协变转换?
假设我们有一些类型Fruit
,Apple
并且Banana
有明显的关系;Apple
是一种Fruit
,以此类推。
协变转换是类型参数的可转换性意味着泛型类型的可转换性。如果Apple
可转换为Fruit
,并且Bowl<Apple>
可转换为Bowl<Fruit>
,则Bowl<T>
在 T 中是协变的。
什么是逆变转换?
逆变转换是反转方向而不是保留方向的协变转换。IfEater<Fruit>
可转换为Eater<Apple>
thenEater<T>
在 T 中是逆变的。
如何在其类型参数中将接口或委托标记为协变或逆变?
协变类型参数被标记out
,逆变类型参数被标记in
。
这是为了助记:协变接口通常具有类型参数出现在输出位置,而逆变接口通常具有类型参数出现在输入位置。
String
可转换为Object
。我怎样才能使IReadOnlyCollection<String>
转换为IReadOnlyCollection<Object>
?
在IReadOnlyCollection<T>
T 中进行协变。标记它out
。
考虑以下代码:
delegate void Action<in T>(T t);
interface IFoo<in X>
{
void M(Action<X> action);
}
为什么编译器说这是无效的?
因为它无效。让我们看看为什么。
class Foo : IFoo<Fruit>
{
public void M(Action<Fruit> action)
{
action(new Apple()); // An apple is a fruit.
}
}
...
IFoo<Fruit> iff = new Foo();
IFoo<Banana> ifb = iff; // Contravariant!
ifb.M(banana => { banana.Peel(); });
遵循逻辑。该程序将苹果作为 的“this”传递Banana.Peel()
,这显然是错误的。
编译器知道这可能会发生,因此不允许首先声明接口。
如果我有更多关于方差的问题,我该怎么办?
您应该首先阅读我关于该功能的设计和实现的文章。从底部开始;它们按时间倒序排列:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
如果您仍有问题,那么您应该在此处发布实际包含问题的问题,而不是让人们猜测问题的真正含义。