2012-02-08 101 views
2

我有一個對象層次是否Enumerable.Cast <T>複製對象?

public class MyBase {} 
public class MyDerived : MyBase {} 

,並有

List<MyBase> myList; 

,實際上是充滿了MyDerived

情況下,爲了訪問列表作爲List<MyDerived>,我做的如下:

myList.Cast<MyDerived>().ToList() 

我讀Enumerable.Cast<T> MSDN文檔,但它不是很清楚,我的Cast<T>ToList操作是否作出新的拷貝到內存中的對象的,或者乾脆讓編譯器訪問現有的對象,好像他們是一List<MyDerived>

+1

它實際上是_impossible_複製任意管理對象。 – SLaks 2012-02-08 18:04:29

回答

5

訪問現有的對象顧名思義,Cast<T>()只是蒙上對象:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) { 
    IEnumerable<TResult> typedSource = source as IEnumerable<TResult>; 
    if (typedSource != null) return typedSource; 
    if (source == null) throw Error.ArgumentNull("source"); 
    return CastIterator<TResult>(source); 
} 

static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) { 
    foreach (object obj in source) yield return (TResult)obj; 
} 

在.NET中,根本不可能複製任意對象。 Cast<T>()複製東西是沒有意義的。

請注意,如果T是值類型,Cast<T>()複製結構;值類型爲總是複製。 (除了當作爲ref參數傳遞)

+0

使用ToList()會創建一個副本,或不? – sos00 2012-02-08 18:10:48

+0

@ sos00:錯了。複製對象是不可能的。 'ToList()'生成_list_的一個副本,但它仍然引用相同的對象。 – SLaks 2012-02-08 18:11:12

+0

在這裏提及你自己的評論可能是有用的:如果有人要像這個_inside_一樣實現這個代碼,那麼包含操作類型的程序集的行爲可能會與標準擴展所做的不同:'(TResult) obj'可以調用用戶定義的轉換運算符(例如'class X {public static implicit operator Y(){...}') – sehe 2012-02-08 18:11:56

0

沒有

不出所料(!),它Casts他們。

我讀Enumerable.Cast MSDN文檔,但它不是很清楚,我的演員和ToList操作是否使對象的新拷貝到內存中,或者乾脆讓編譯器來訪問現有的對象,就好像他們是一個列表。

是的,特別是這種方案將允許編譯器,就好像他們是一個List<MyDerived>

+0

用戶定義的轉換純粹是編譯時功能;沒有運行時方法曾經使用它們。 – SLaks 2012-02-08 18:07:01

+0

@SLaks:再次感謝。我今天學到了東西。你救了我努力嘗試:) – sehe 2012-02-08 18:09:15

0

鑄造呼叫:

enumerable.Cast<T>(); 

相當於:

enumerable.Select(x=>(T)x) 

和:

enumerable.ToList<T>() 

相當於:

List<T> myList = new List<T>(); 
foreach(T item in enumerable) 
{ 
    myList.Add(item); 
} 

so ...

enumerable.Cast<T2>.ToList() 

相當於:

List<T2> myList = new List<T2>(); 
foreach(T item in enumerable) 
{ 
    myList.Add((T2)item); 
} 

這兩者會及時炸燬如果枚舉包含是一種類型的可澆注到T2的不任何條目。

這將是更安全的

enumerable.Where(x=>x is T2).Cast<T2>().ToList(); 

enumerable.OfType<T2>().ToList(); 

然而,這些副本中包含原始集合中的對象。他們只是創建包含對原始對象的引用的集合。

+0

因此分配給新列表的內存_is_ ? – 2012-02-08 22:55:52

+0

是的。內存分配給列表數據結構。 – 2012-02-14 19:11:39

+0

注意:我使用OfType擴展方法添加了另一種替代方法,該方法可以過濾並轉換爲定義的類型。 (enumerable.OfType ().ToList())將只返回可轉化爲T2類型的元素的列表。 – 2012-02-14 19:17:48