我想我可以将IList<ChildClass>
作为IEnumerable<ParentClass>
传递,因为ChildType列表中的每个对象显然也是ParentType的一个实例。但是我没有得到编译器的喜爱。我错过了什么?
编辑:添加功能Foo3,它做我想要的。谢谢!
namespace StackOverflow
{
public class ParentClass
{
}
public class ChildClass : ParentClass
{
}
public class Test
{
// works
static void Foo(ParentClass bar2)
{
}
// fails
static void Foo2(IEnumerable<ParentClass> bar)
{
}
// EDIT: here's the right answer, obtained from the
// Charlie Calvert blog post
static void Foo3<T>(IEnumerable<T> bar) where T : ParentClass
{
}
public static void Main()
{
var childClassList = new List<ChildClass>();
// this works as expected
foreach (var obj in childClassList)
Foo(obj);
// this won't compile
// Argument '1': cannot convert from
// 'System.Collections.Generic.List<ChildClass>'
// to 'System.Collections.Generic.IEnumerable<ParentClass>'
Foo2(childClassList);
// EDIT: this works and is what I wanted
Foo3(childClassList);
}
}
}
答案 0 :(得分:5)
答案 1 :(得分:2)
您缺少通用差异,目前在C#中不存在。我相信你的代码可以在C#4.0中运行。
这是其他问题的重复...
请参阅:
List<string>
be stored in a List<object>
variable IEnumerable<Object>
to IEnumerable<String>
答案 2 :(得分:1)
您应该在Eric Lippert's Covariance and Contravariance series中找到所需的全部内容。这是一个相当多的阅读,但回答(a)为什么你不能在C#3.0中这样做,以及(b)为什么你能够在C#4.0中做到这一点。
答案 3 :(得分:0)
我担心通用参数类型没有隐式转换(没有“通用方差”似乎是技术术语)。不确定我能给你更深入的解释,但我会接受它作为CLR的工作方式......
您只需要在childClassList上使用 Cast 扩展方法将列表强制转换为IEnumerable。
答案 4 :(得分:0)
虽然在IList和IEnumerable的情况下可以解决问题,但是当你把它看作收集和集合时,编译器无法真正知道它。
如果你可以使用集合作为集合,有人可以尝试在集合中添加一个父...编译器必须阻止它。