簡體   English   中英

泛型鑄造

[英]Generics type casting

我只是在.NET泛型類型轉換中沒有得到什么。 有人可以解釋下面的代碼片段中會發生什么嗎?

void Main()
{
    IEnumerable<int> ints = new List<int>();
    IEnumerable<string> strings = new List<string>();

    var rez1=(IEnumerable<object>)ints; //runtime error
    var rez2=(IEnumerable<object>)strings; //works
    var rez3=(List<object>)strings; //runtime error
}

讓我們從第二行開始,這是最簡單的。

這鑄作品,因為類型參數IEnumerable<T>現在是協變 (這是什么outout T一樣)。 這意味着您可以自由地將IEnumerable<Derived>轉換為IEnumerable<Base>

第一行似乎是相同的情況,因為int是值類型,所以不起作用。 接口方差根本不適用於值類型,因為值類型並不真正從System.Object繼承; 它們可以被裝箱object ,但是這是不一樣的。 文件提到了這一點

差異僅適用於參考類型; 如果為變量類型參數指定值類型,則該類型參數對於生成的構造類型是不變的。

最后,第三行不起作用,因為List<T>的類型參數是不變的 你可以看到它的類型參數沒有out ; 規則不允許因為List<T>不是接口:

在.NET Framework 4中,變體類型參數僅限於通用接口和通用委托類型。

這是因為界面協方差僅適用於引用類型。 當然,Int32是一種值類型。

這提供了更多信息: http//blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx

這樣做: http//ericlippert.com/2011/09/19/inheritance-and-representation/

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中泛型類型背后的機制不能用於這些類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM