协变和逆变上同一类型的参数 [英] Covariance and Contravariance on the same type argument

查看:139
本文介绍了协变和逆变上同一类型的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#的规范规定的参数类型不能同时协变和逆变在同一时间。



这创造你装饰协变或逆变接口时,很明显你类型参数分别为中,去或。没有选项,允许同时在同一时间(outin)。



这是限制只是一个语言特定约束还是有更深,基于在更基本的原因?范畴理论,将让你不希望你的类型既协变和逆变



编辑:



我的理解是,数组实际上是两个协变和逆变。

 公共类宠物{} 
酒店的公共类猫:宠物{}
公共类连体:猫{}
猫[] =猫新型卡特彼勒[10];
宠物[] =宠物的新宠物[10];
连体[] = siameseCats新连体[10];

//猫数组是协变的
=宠物猫;
//猫阵列也逆变,因为它接受来自更广泛的类型
=猫转换siameseCats;


解决方案

正如其他人所说,这是一个逻辑上不一致泛型类型既协变和逆变。有一些优秀的答案在这里,到目前为止,但让我补充两个



首先,请阅读我的方差有效性的主题文章:



http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx



根据定义,如果一个类型是协变合法,那么它​​的在逆变方式的不能使用。如果是contravariantly有效,那么它​​的的协变的方式不能使用的。东西是的两个的协变有效,contravariantly是有效的在任何一个协变或逆变方式无法使用的。即,它是<青霉>不变的。因此,有的协变和逆变的工会。工会是的不变



二,假设为你有你的愿望,而且有一个类型的注释,工作,我想你想的方式了一下:

 接口IBurger<进出T> {} 



假设你有一个 IBurger<串> 。因为它是协变,那就是转换为 IBurger<对象> 。因为它是逆变的,就是反过来转换为 IBurger<异常和GT; ,尽管串和异常的共同点毫不相干。基本上是进出是指 IBurger< T1> 可转换为的任何的类型 IBurger< T2> 对于任何两个引用类型T1和T2。的这怎么用?的你会怎么的有这样的功能?假设你有一个 IBurger<异常> ,但对象实际上是一个 IBurger<串> 。你可以与该做些什么,既利用了一个事实,即类型参数是例外,并允许该类型参数是一个彻头彻尾的谎言,因为真正的式的说法是完全不相关的类型?



要回答你的后续问题:涉及阵列隐式引用类型转换的的;他们的的逆变。你能解释一下为什么你错误地认为他们被逆变?


The C# spec states that an argument type cannot be both covariant and contravariant at the same time.

This is apparent when creating a covariant or contravariant interface you decorate your type parameters with "out" or "in" respectively. There is not option that allows both at the same time ("outin").

Is this limitation simply a language specific constraint or are there deeper, more fundamental reasons based in category theory that would make you not want your type to be both covariant and contravariant?

Edit:

My understanding was that arrays were actually both covariant and contravariant.

public class Pet{}
public class Cat : Pet{}
public class Siamese : Cat{}
Cat[] cats = new Cat[10];
Pet[] pets = new Pet[10];
Siamese[] siameseCats = new Siamese[10];

//Cat array is covariant
pets = cats; 
//Cat array is also contravariant since it accepts conversions from wider types
cats = siameseCats; 

解决方案

As others have said, it is logically inconsistent for a generic type to be both covariant and contravariant. There are some excellent answers here so far, but let me add two more.

First off, read my article on the subject of variance "validity":

http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx

By definition, if a type is "covariantly valid" then it is not usable in a contravariant way. If it is "contravariantly valid" then it is not usable in a covariant way. Something that is both covariantly valid and contravariantly valid is not usable in either a covariant or contravariant way. That is, it is invariant. So, there is the union of covariant and contravariant: their union is invariant.

Second, let's suppose for a moment that you got your wish and that there was a type annotation that worked the way I think you want:

interface IBurger<in and out T> {}

Suppose you have an IBurger<string>. Because it is covariant, that is convertible to IBurger<object>. Because it is contravariant, that is in turn convertible to IBurger<Exception>, even though "string" and "Exception" have nothing whatsoever in common. Basically "in and out" means that IBurger<T1> is convertible to any type IBurger<T2> for any two reference types T1 and T2. How is that useful? What would you do with such a feature? Suppose you have an IBurger<Exception>, but the object is actually an IBurger<string>. What could you do with that, that both takes advantage of the fact that the type argument is Exception, and allows that type argument to be a complete lie, because the "real" type argument is an utterly unrelated type?

To answer your follow-up question: implicit reference type conversions involving arrays are covariant; they are not contravariant. Can you explain why you incorrectly believe them to be contravariant?

这篇关于协变和逆变上同一类型的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆