我最近在尝试将AddRange(IEnumerable)添加到列表时遇到麻烦。可能是经典问题,但我还没有真正理解。
我知道期望List参数的方法对List并不满意,因为它们可能会尝试将Base添加到List中,这显然是不可能的。
但是,如果我正确地做到这一点,由于IEnumerables本身无法更改,因此在这种情况下应该可以使用。
我想到的代码如下所示:
class Foo
{
}
class Bar : Foo
{
}
class FooCol
{
private List<Foo> m_Foos = new List<Foo> ();
public void AddRange1(IEnumerable<Foo> foos)
{
m_Foos.AddRange (foos); // does work
}
public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
{
m_Foos.AddRange (foos); // does not work
}
}
class Program
{
static void Main(string[] args)
{
FooCol fooCol = new FooCol ();
List<Foo> foos = new List<Foo> ();
List<Bar> bars = new List<Bar> ();
fooCol.AddRange1 (foos); // does work
fooCol.AddRange1 (bars); // does not work
fooCol.AddRange2 (foos); // does work
fooCol.AddRange2 (bars); // does work
}
}
我试图在AddRange2方法中向编译器传递一个提示,但这只是解决了问题。
我的思维方式有缺陷吗?这是语言的限制还是设计上的限制?
IIRC,对此类操作的支持已添加到Java 1.5中,所以也许将来还会在C#中添加它……?
最佳答案
这是协方差,将在C#4.0/.NET 4.0中修复。目前,泛型选项是最佳答案(对于IEnumerable<T>
-not IList<T>
etc)。
但是在通用方法中,您必须考虑T
。您也可以在LINQ中使用Cast<T>
或OfType<T>
来实现类似的目的。