2009-02-11 31 views
5

我有一個IList<DerivedClass>,我想投到ICollection<BaseClass>,但是當我嘗試進行明確演員時,我得到了null。有沒有可能做到這一點,而無需創建和填充新的集合?將一個通用集合投射到基類型

編輯: 因爲我只想從集合中讀取,我轉而使用泛型方法:

public void PopulateList<BaseClass>(ICollection<T> collection) 

那麼我可以通過它的IList<DerivedClass>。有沒有一種好的方法來緩存這個列表,以便在需要時可以刷新它。我的第一個傾向是使用:

Object cachedCollection; 
Type cachedType; 
public void PopulateList<BaseClass>(ICollection<T> collection) { 
    cachedCollection = collection; 
    cachedType = T; 

    // other stuff... 
} 

private void Refresh() { 
    PopulateList<cachedType>(cachedCollection as ICollection<cachedType>); 
} 

有沒有人有更好的方式做到這一點?

+0

代碼示例會非常有幫助。沒有它,很難給你任何有用的答案。 – 2009-02-11 23:11:38

回答

8

簡短答案是「否」您需要使用新的BaseClass類型創建一個新的集合並填充它。

如果你仔細想想,這是有道理的。如果你可以簡單地將你的集合「轉換」到BaseClass,那麼你可以將一些類型爲「BaseClass」的東西插入它,從而強制一個簡單的BaseClass對象進入DerivedClass集合。這將破壞創建類型安全收集的目的。

在極端情況下,如果您有兩個派生類Foo和Bar,則可以通過將集合類型轉換回BaseClass集合來強制Bar對象進入Foo對象的集合。

+0

這是有道理的。我只是從收藏中讀取的,所以我沒有想到我想要做的事情的全部含義。 – dmo 2009-02-11 23:25:29

+0

var baseCollection =(ICollection)derivedList.CastToList (); – 2010-12-29 21:37:51

3

我不認爲這是可能的,而且確實不應該是:

class BaseClass {} 
class DerivedClass : BaseClass {} 
class OtherClass : BaseClass {} 

void test() 
{ 
    List<DerivedClass> list = new List<DerivedClass>(); 
    slice(list); //you want to do this 
} 

void slice(IList<BaseClass> list) 
{ 
    //yikes! adding OtherClass to List<DerivedClass> 
    list.Add(new OtherClass()); 
} 
+1

在.NET 4.0中,這種情況通過使用「in」和「out」關鍵字來解決。 – 2010-09-03 20:48:04

2

派生類和基類的泛型容器之間的切換不被支持。 (它可以與數組一起工作)可以編寫一個類型轉換器來合理乾淨地執行切換,而無需在列表之間手動複製元素。

退房此鏈接的問題/限制的說明和解決方案: http://www.25hoursaday.com/weblog/CommentView.aspx?guid=AF7AA888-A227-454C-8687-71FA77186064

唐氏在底部是一個不錯的啓用通用版本。

+0

是的,ConvertAll是你的朋友在這裏:) – 2009-02-11 23:40:29

6

這被稱爲協方差,雖然目前不支持泛型在.net中,但它將被添加到4.0框架中(以及相反的是反方差)。

從2008年PDC這個出色的視頻是在C#期貨會議由安德斯·海爾斯伯格給出:

http://channel9.msdn.com/pdc2008/TL16/

2

如果.NET 3.5是一個選項,你可以使用System.Core.dllCast<T>擴展方法得到一個讀 - 只IEnumerable<T>的收集:

using System.Linq; 
... 
private void Refresh() { 
    PopulateList(cachedCollection.Cast<cachedType>()); 
} 
0

你可以施放的每個元素到新的迭代:

var collectionOfBase = (collectionOfDerived as IEnumerable).Cast<BaseClass>(); 
相關問題