[英]Why `IEnumerable<int>` is not `IEnumerable<object>`?
IEnumerable<T>
接口是协变的,因此IEnumerable<string>
是IEnumerable<object>
。 但是为什么IEnumerable<int>
不是IEnumerable<object>
而int
是object
?
只有在类型参数之间存在隐式引用或标识转换时,才支持像这样的变体转换。 正如规范所说:
类型
T<Aᵢ, ..., Aᵥ>
可以变体转换为类型T<Bᵢ, ..., Bᵥ>
如果T
是接口或使用变体类型参数T<Xᵢ, ..., Xᵥ>
,并且对于每个变体类型参数Xᵢ
以下之一成立:
Xᵢ
是协变的,存在从Aᵢ
到Bᵢ
的隐式引用或身份转换Xᵢ
是逆变的,存在从Bᵢ
到Aᵢ
的隐式引用或身份转换Xᵢ
是不变的,存在从Aᵢ
到Bᵢ
的身份转换
int
和object
之间既没有引用也没有身份转换,只有装箱转换。
您可能想知道隐式引用和身份转换有什么特别之处,以至于它们允许差异转换。 好吧,这些转换根本不需要运行时做任何事情!
例如,从string
转换为object
纯粹是编译时的事情。 无需对表示string
的位进行任何操作,即可将其转换为object
。 毕竟,每个string
都是object
。
因此,从IEnumerable<string>
转换为IEnumerable<object>
也很简单——运行时不需要做任何事情。
但是,对于int
到object
的转换,情况并非如此。 因为int
是值类型, object
是引用类型。 为了维护这些语义,运行时需要围绕该int
创建一个引用类型包装器以便进行转换,“装箱”它。
这意味着如果运行时想要将IEnumerable<int>
转换为IEnumerable<object>
,它不能只是“什么都不做”。 您希望从IEnumerable
中获取引用类型,而不是值类型,那么“装箱”何时以及如何发生? 一般来说,这应该在何时以及如何发生,而不仅仅是在IEnumerable<T>
的情况下?
我相信这在理论上都可以被弄清楚、设计和实现,但它肯定不会像隐式引用转换那样微不足道。 事实上,我认为它会复杂得多,并且需要对语言和运行时进行非常剧烈的更改,这可能是未实现的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.