[英]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.