我最近在尝试将 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
.您也可以使用 Cast<T>
或 OfType<T>
使用 LINQ 来实现类似的功能。
关于C# 无法从 IEnumerable<Base> 转换为 IEnumerable<Derived>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/634268/