微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Covariance & Contra-variance之间的区别

如何解决Covariance & Contra-variance之间的区别

问题是“Covariance & Contra-variance有什么区别?”

Covariance & Contra-variance是映射函数属性它将集合的一个成员与另一个成员相关联。更具体地说,映射可以相对于该集合上的关系是协变或逆变的。

考虑所有 C# 类型集的以下两个子集。第一的:

{ Animal, 
  Tiger, 
  Fruit, 
  Banana }.

其次,这个明显相关的集合:

{ IEnumerable<Animal>, 
  IEnumerable<Tiger>, 
  IEnumerable<Fruit>, 
  IEnumerable<Banana> }

从第一组到第二组有一个映射操作。也就是说,对于第一组中的每个 T,第二组中对应的类型是IEnumerable<T>。或者,简而言之,映射是T → IE<T>. 请注意,这是一个“细箭头”。

跟我到现在?

现在让我们考虑一个关系。第一组类型对之间存在赋值兼容关系。type 的值Tiger可以分配给 type 的变量Animal,因此这些类型被称为“赋值兼容”。让我们用更短的形式写“一个类型的值X可以分配给一个类型的变量”: 。请注意,这是一个“胖箭头”。Y``X ⇒ Y

所以在我们的第一个子集中,这里是所有的赋值兼容性关系:

Tiger  ⇒ Tiger
Tiger  ⇒ Animal
Animal ⇒ Animal
Banana ⇒ Banana
Banana ⇒ Fruit
Fruit  ⇒ Fruit

支持某些接口的协变赋值兼容性的 C# 4 中,第二组类型对之间存在赋值兼容性关系:

IE<Tiger>  ⇒ IE<Tiger>
IE<Tiger>  ⇒ IE<Animal>
IE<Animal> ⇒ IE<Animal>
IE<Banana> ⇒ IE<Banana>
IE<Banana> ⇒ IE<Fruit>
IE<Fruit>  ⇒ IE<Fruit>

请注意,映射T → IE<T> 保留了赋值兼容性的存在和方向。也就是说,如果X ⇒ Y,那么 也是如此IE<X> ⇒ IE<Y>

如果我们在粗箭头的两边有两个东西,那么我们可以用相应的细箭头右侧的东西来替换两边。

对于特定关系具有此属性的映射称为“协变映射”。这应该是有道理的:可以在需要动物序列的地方使用 Tigers 序列,但反之则不然。在需要老虎序列的情况下,不一定要使用动物序列。

这就是协方差。现在考虑所有类型集合的这个子集:

{ IComparable<Tiger>, 
  IComparable<Animal>, 
  IComparable<Fruit>, 
  IComparable<Banana> }

现在我们有了从第一组到第三组的映射T → IC<T>

在 C# 4 中:

IC<Tiger>  ⇒ IC<Tiger>
IC<Animal> ⇒ IC<Tiger>     Backwards!
IC<Animal> ⇒ IC<Animal>
IC<Banana> ⇒ IC<Banana>
IC<Fruit>  ⇒ IC<Banana>     Backwards!
IC<Fruit>  ⇒ IC<Fruit>

即映射T → IC<T>保留了存在性,但反转了赋值兼容的方向。也就是说,如果X ⇒ Y,那么IC<X> ⇐ IC<Y>

保留但反转关系的映射称为逆变映射。

同样,这应该是正确的。可以比较两只动物的设备也可以比较两只老虎,但是可以比较两只老虎的设备不一定能比较任何两只动物。

这就是 C# 4 中协变和逆变之间的区别。协变保留了可分配性的方向。逆变将它反转

解决方法

我无法理解协Covariance & Contra-variance间的区别。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。