好的,我想将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!
// .........
}
答案 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>();
无论如何,你最好使用接口...... :)