我有两个IList<ICat>
,我正在尝试创建一个方法,它接受IList<ICat>
并做一些工作。我在尝试向其IList<PussyCat>
或IList<OtherCat>
传递时遇到问题,PussyCat
和OtherCat
实施ICat
。
我试过了:
List<PussyCat> cats = ...
DoWork((IList<ICat>)cats);
只是
DoWork(cats);
但是没有编译。有什么想法吗?
答案 0 :(得分:7)
C#泛型是不变的。这意味着List<string>
不是List<object>
。
C#4.0引入了safe covariance/contravariance,但您仍然无法将List<string>
作为List<object>
传递。原因是:
List<string> x = new List<string>();
List<object> o = x; // assume this statement is valid
o.Add(5); // Adding an integer to a list of strings. Unsafe. Will throw.
另一方面,阵列是协变的。您可以将string[]
传递给期望object[]
的方法。
答案 1 :(得分:5)
有两种选择:
按照以下方式制作您的方法:
public void DoWork< T > (IList< T > cats_) where T : ICat
{
//Do work;
}
另一种可能性是使用像
这样的方法public void DoWork(IList< ICat > cats_)
{
//Do work;
}
并按以下方式调用它:
{
//....Assuming: IList<PussyCat> iListOfPussyCats
List<PussyCat> pussyCats = new List<PussyCats>(iListOfPussyCats);
DoWork(pussyCats.ConvertAll<ICat>( c => c as ICat);
}
答案 2 :(得分:1)
如果该方法不需要直接索引(IList<T>
)并且不需要添加/删除项目(ICollection<T>
),则传递IEnumerable<T>
。 Cast<T>()
扩展程序允许将任何IList
[insert ICat
- 派生类型]转换为IEnumerable<ICat>
。
答案 3 :(得分:0)
直到C#4.0到达,它支持co和contra方差,你可能会得到这样的东西:
public void DoWork(IEnumerable<ICat> cats)
{
//do something
}
List<PussyCat> pussyCats = new List<PussyCat>;
List<OtherCat> otherCats = new List<OtherCat>;
DoWork(pussyCats.OfType<ICat>);
DoWork(otherCats.OfType<ICat>);