2009-08-14 75 views
1

可能重複的一些問題:
Upcasting and generic lists與發送列表<T>爲IEnumerable <T>的方法

好吧,我想送一個List<CardHolder>IEnumerable<ICardHolder>其中CardHolder : ICardHolder。然而,編譯器錯誤:

錯誤4參數 '1':無法從 'System.Collections.Generic.List' 到 'System.Collections.Generic.IEnumerable' 轉換

這似乎很奇怪對我來說,考慮一個List<T> : IEnumerable<T>。出了什麼問題?

public interface ICardHolder 
{ 
    List<Card> Cards { get; set; } 
} 

public class CardHolder : ICardHolder 
{ 
    private List<Card> cards = new List<Card>(); 
    public List<Card> Cards 
    { 
     get { return cards; } 
     set { cards = value; } 
    } 

    // ........ 
} 

public class Deck : ICardHolder 
{ 
    // ......... 

    public void Deal(IEnumerable<ICardHolder> cardHolders) 
    { 
     // ........ 
    } 

    // ......... 
} 

public class Game 
{ 
    Deck deck = new Deck(); 
    List<CardHolder> players = new List<CardHolder>(); 

    // ......... 

    deck.Deal(players); // Problem is here! 

    // ......... 
} 

回答

7

問題是List<T>不是IEnumerable<T1>即使T : T1亞型。

C#中的泛型(C#4.0之前)是「不變的」(即沒有這種子類型關係)。在.Net 4中,IEnumerable<T>將其類型參數標註爲「協變」。這意味着如果T : T1List<T>將是IEnumerable<T1>的子類型。

有關此功能的更多詳細信息,請參閱MSDN上的this page

編輯 - 您可以通過使Deal方法的通用解決這個在您的情況:

public void Deal<T>(IEnumerable<T> cardHolders) where T : ICardHolder 
{ 
    // ........ 
} 
+0

沒有,所以我需要將我的列表轉換爲列表能夠將它作爲IEnumerable 發送?哦,是否有可能在VS2008上獲得某種C#4.0的預覽? – 2009-08-14 21:41:01

+1

這裏有一篇關於泛型中的co/contravariance的優秀InfoQ文章:http://www.infoq.com/news/2008/08/GenericVariance – 2009-08-14 21:41:39

+0

+50泛型方法(如果可以的話)。謝謝! – 2009-08-14 21:50:35

0

添加到Ben的答案,則應更換行:

List<CardHolder> players = new List<CardHolder>(); 

有:

List<ICardHolder> players = new List<ICardHolder>(); 

你是不管怎麼說接口更好...... :)

+0

不幸的是,這不適用於我有的其他代碼,因爲它需要訪問ICardHolder沒有(也不能)擁有的CardHolder的某些特定屬性。不過謝謝。 – 2009-08-14 21:43:05

+0

對於CardHolder特定屬性,您始終可以投射到CardHolder ... – 2009-08-14 21:48:25

1

A List<CardHolder>IEnumerable<CardHolder>,但IEnumerable<CardHolder>不是IEnumerable<ICardHolder>。這兩個接口是無關的(除了它們的結構)。

C#4.0引入了協變和逆變,可以解決這樣的問題

同時,在C#3.0中,你可以這樣做:

deck.Deal(players.Cast<ICardHolder>()); 

應該沒有顯著的性能影響,因爲收藏品是隻枚舉了一次,並upcast ICardHolder是MSIL

相關問題