将List <t>作为IEnumerable <t>发送到方法</t> </t>的一些问题

时间:2009-08-14 21:33:01

标签: c# .net generics interface ienumerable

  

可能重复:
  Upcasting and generic lists

好的,我想将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!

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

3 个答案:

答案 0 :(得分:7)

问题是即使List<T>IEnumerable<T1>也不是T : T1的子类型。

C#中的泛型(在C#4.0之前)是“不变的”(即没有这种子类型关系)。在.Net 4中,IEnumerable<T>将其类型参数注释为'covariant'。这意味着如果List<T>IEnumerable<T1>将成为T : T1的子类型。

有关此功能的详细信息,请参阅MSDN上的this page

修改 - 您可以通过将Deal方法设为通用来解决此问题:

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

答案 1 :(得分:1)

List<CardHolder>IEnumerable<CardHolder>,但IEnumerable<CardHolder>不是IEnumerable<ICardHolder>。这两个接口是不相关的(除了它们的结构)。

C#4.0引入了协方差和逆变,可以解决这类问题

同时,在C#3.0中,你可以这样做:

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

它应该没有显着的性能影响,因为该集合只被枚举一次,并且ICardHolder的上传是MSIL中的无操作

答案 2 :(得分:0)

根据Ben的回答,您应该替换以下行:

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

使用:

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

无论如何,你最好使用接口...... :)