为什么协变和逆变不支持值类型 [英] Why covariance and contravariance do not support value type

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

问题描述

的IEnumerable< T> 合变的,但它不支持值类型,仅仅只引用类型。下面简单的code成功编译:

IEnumerable<T> is co-variant but it does not support value type, just only reference type. The below simple code is compiled successfully:

IEnumerable<string> strList = new List<string>();
IEnumerable<object> objList = strList;

不过从字符串更改为 INT 将得到编译错误:

But changing from string to int will get compiled error:

IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList;

原因是在<一个解释href="http://msdn.microsoft.com/en-us/library/dd799517.aspx#InterfaceCovariantTypeParameters">MSDN:

差异仅适用于引用类型;如果你指定一个变量类型参数的值类型,该类型参数是不变的结果构造类型。

Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.

我已搜查,发现了一些问题提到的原因的的值类型和引用类型拳击的。不过,这并不尚清了我的心多,为什么拳击是什么原因呢?

I have searched and found that some questions mentioned the reason is boxing between value type and reference type. But it does not still clear up my mind much why boxing is the reason?

可能有人请举一个简单的和详细的解释,为什么协变和逆变不支持值类型,以及如何的拳击的影响呢?

Could someone please give a simple and detailed explanation why covariance and contravariance do not support value type and how boxing affects this?

推荐答案

基本上,差异适用于当CLR可以确保它不需要做任何的再presentational变化应用于值。引用看起来都一样 - 这样你就可以使用的IEnumerable&LT;字符串&GT; 的IEnumerable&LT;对象&gt; 无任何改变在重新presentation; C本身天然$ C $并不需要知道自己在做什么的价值观可言,只要基础设施保证它一定是有效的。

Basically, variance applies when the CLR can ensure that it doesn't need to make any representational change to the values. References all look the same - so you can use an IEnumerable<string> as an IEnumerable<object> without any change in representation; the native code itself doesn't need to know what you're doing with the values at all, so long as the infrastructure has guaranteed that it will definitely be valid.

有关值类型,不工作 - 以治疗的IEnumerable&LT; INT&GT; 的IEnumerable&LT;对象&gt; ,使用序列code必须知道是否执行装箱转换与否。

For value types, that doesn't work - to treat an IEnumerable<int> as an IEnumerable<object>, the code using the sequence would have to know whether to perform a boxing conversion or not.

您可能需要阅读埃里克利珀的博客文章上再presentation和身份获得更多关于这个话题一般。

You might want to read Eric Lippert's blog post on representation and identity for more on this topic in general.

编辑:经重读埃里克的博客张贴自己,这至少相当于约的的身份的作为再presentation,尽管两者有联系。特别是:

Having reread Eric's blog post myself, it's at least as much about identity as representation, although the two are linked. In particular:

这就是为什么接口和委托类型的协变和逆变转换要求所有不同类型的参数是引用类型。为了确保变种引用转换始终是身份 - preserving,所有涉及类型参数的转换也必须是身份 - preserving。确保所有的类型参数的不平凡的转换是身份 - preserving最简单的方法是限制他们要引用转换。

This is why covariant and contravariant conversions of interface and delegate types require that all varying type arguments be of reference types. To ensure that a variant reference conversion is always identity-preserving, all of the conversions involving type arguments must also be identity-preserving. The easiest way to ensure that all the non-trivial conversions on type arguments are identity-preserving is to restrict them to be reference conversions.

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

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