这个问题好像没有什么问题,所以我就编几个问题来回答一下。
什么是协变转换?
假设我们有一些类型Fruit
and Apple
and Banana
具有明显的关系;Apple
是一种Fruit
, 等等。
协变转换是一种类型参数的可转换性意味着泛型类型的可转换性的转换。如果Apple
可转换为Fruit
, and Bowl<Apple>
可转换为Bowl<Fruit>
, then Bowl<T>
T 中是协变的。
什么是逆变转换?
逆变转换是协变转换,reverses方向而不是保存 it. If Eater<Fruit>
可转换为Eater<Apple>
then Eater<T>
在 T 中是逆变的。
如何将接口或委托的类型参数标记为协变或逆变?
协变类型参数已标记out
并标记逆变类型参数in
.
这是为了便于记忆:协变接口通常使类型参数出现在输出位置,而逆变接口通常使类型参数出现在输入位置。
String
可转换为Object
。我怎样才能使IReadOnlyCollection<String>
可转换为IReadOnlyCollection<Object>
?
Make IReadOnlyCollection<T>
T 中的协变。Mark itout
.
考虑以下代码:
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/
如果您仍然有问题,那么您应该在此处发布实际包含问题的问题,而不是让人们猜测问题到底是什么。