每從System.ValueType
導出,具有System.Enum
異常類型的定義,實際上定義了兩種類型的東西:一個堆對象類型,以及一個存儲位置類型。後者的實例可以隱含地轉換爲前者(製作其中包含的數據的副本),前者的實例可以明確地向後者的類型轉換(同樣);即使這兩種東西都是由相同的System.Type
描述的,雖然它們具有相同的成員,但它們的行爲卻非常不同。
甲List<AnyClassType>
將預期保持一堆堆對象引用的;有問題的列表是否是List<String>
,List<StringBuilder>
,List<Button>
,或什麼的,可能會感興趣的名單的用戶,但不是真正感興趣的List<T>
本身。如果一個人蒙上了List<Button>
到IEnumerable<Control>
,別人誰調用它的GetEnumerator()
方法會希望得到一個對象,它將對從Control
獲得堆對象輸出參考;從List<Button>.GetEnumerator()
回報將滿足這一期望。相比之下,如果有人將List<Int32>
轉換爲List<Object>
,那麼調用GetEnumerator()
的人會期望可以輸出堆對象引用的內容,但List<Integer>.GetEnumerator
將會產生輸出值類型整數的內容。
可以將Int32
值存儲到List<Object>
或List<ValueType>
;將整數存儲到這樣的列表將會將其轉換爲其堆對象形式並存儲對其的引用;調用GetEnumerator()
會產生輸出堆引用的東西。但是,沒有辦法指定這樣的列表將僅包含對應於Int32
的堆類型的實例。在C++/CLI中,可以聲明類型爲「引用堆存儲的值類型」的變量,但.net中的泛型類型背後的機制不能用於這種類型。
但Int32可以轉換爲Object。這不足以作出協變嗎?或者它是一個編譯器功能? – Vasaka
@Vasaka:這是一個裝箱操作,而不是參考轉換。這是技術性的,但是儘管編譯器在每種情況下都具有相同的語法,但完全不同。 – Jon
...正如所有泛型類和結構的類型參數一樣;僅支持接口和委託類型的類型差異。 – phoog