繁体   English   中英

为什么`IEnumerable<int> ` 不是 `IEnumerable<object> `?<div id="text_translate"><p> IEnumerable<T>接口是协变的,因此IEnumerable<string>是IEnumerable<object> 。 但是为什么IEnumerable<int><em><strong>不是</strong></em>IEnumerable<object>而int是object ?</p></div></object></int>

[英]Why `IEnumerable<int>` is not `IEnumerable<object>`?

IEnumerable<T>接口是协变的,因此IEnumerable<string>IEnumerable<object> 但是为什么IEnumerable<int>不是IEnumerable<object>intobject

只有在类型参数之间存在隐式引用标识转换时,才支持像这样的变体转换。 正如规范所说:

类型T<Aᵢ, ..., Aᵥ>可以变体转换为类型T<Bᵢ, ..., Bᵥ>如果T是接口或使用变体类型参数T<Xᵢ, ..., Xᵥ> ,并且对于每个变体类型参数Xᵢ以下之一成立:

  • Xᵢ是协变的,存在从AᵢBᵢ的隐式引用或身份转换
  • Xᵢ是逆变的,存在从BᵢAᵢ的隐式引用或身份转换
  • Xᵢ是不变的,存在从AᵢBᵢ的身份转换

intobject之间既没有引用也没有身份转换,只有装箱转换。

您可能想知道隐式引用和身份转换有什么特别之处,以至于它们允许差异转换。 好吧,这些转换根本不需要运行时做任何事情!

例如,从string转换为object纯粹是编译时的事情。 无需对表示string的位进行任何操作,即可将其转换为object 毕竟,每个string都是object

因此,从IEnumerable<string>转换为IEnumerable<object>也很简单——运行时不需要做任何事情。

但是,对于intobject的转换,情况并非如此。 因为int是值类型, object是引用类型。 为了维护这些语义,运行时需要围绕该int创建一个引用类型包装器以便进行转换,“装箱”它。

这意味着如果运行时想要将IEnumerable<int>转换为IEnumerable<object> ,它不能只是“什么都不做”。 您希望从IEnumerable中获取引用类型,而不是值类型,那么“装箱”何时以及如何发生? 一般来说,这应该在何时以及如何发生,而不仅仅是在IEnumerable<T>的情况下?

我相信这在理论上都可以被弄清楚、设计和实现,但它肯定不会像隐式引用转换那样微不足道。 事实上,我认为它会复杂得多,并且需要对语言和运行时进行非常剧烈的更改,这可能是未实现的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM