I figured I could pass an IList<ChildClass>
as an IEnumerable<ParentClass>
, since obviously each object in a ChildType list is also an instance of ParentType. But I'm gettin no love from the compiler. What am I missing?
我认为可以将IList
EDIT: Added function Foo3 which does what I want. Thanks!
编辑:添加了函数Foo3,这是我想要的。谢谢!
namespace *
{
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);
}
}
}
5 个解决方案
#1
5
Because generics aren't co/contra variant:
因为泛型不是co/contra变体:
Eric Lippert's blog has a great post on this.
Eric Lippert的博客上有一篇关于这方面的文章。
Another article from Charlie Calvert is here.
Charlie Calvert的另一篇文章在这里。
#2
2
You're missing generic variance, which doesn't exist in C# at the moment. Your code would work in C# 4.0, I believe.
您正在丢失泛型方差,这在c#中是不存在的。我相信您的代码在c# 4.0中可以工作。
This is a duplicate of other questions though...
这是其他问题的重复……
See:
看到的:
- Why can't a
List<string>
be stored in aList<object>
variable -
为什么列表
不能存储在列表 - How does C# 4.0 Generic Covariance and Contra-Variance implemented
- c# 4.0通用协方差和逆变方差如何实现
- Is there a way to cast generic lists to lists of interface/base class types
- 是否有一种方法可以将泛型列表转换为接口/基类类型的列表
- C# .NET passing a collection of InterfaceImplementingClass objects to a routine that takes a collection of Interface objects
- .NET将InterfaceImplementingClass对象的集合传递给一个例程,该例程接受接口对象的集合
- Casting from
IEnumerable<Object>
toIEnumerable<String>
- 从IEnumerable
#3
1
You should find all you're looking for in Eric Lippert's Covariance and Contravariance series. It's a fair bit of reading, but answers (a) why you can't do this in C# 3.0, and (b) why you will be able to do it i C# 4.0.
你应该在Eric Lippert的协方差和逆变级数中找到你要找的所有东西。这是一个很好的阅读材料,但是回答(a)为什么你不能在c# 3.0中这样做,(b)为什么你可以在c# 4.0中这样做。
#4
0
I'm afraid there's no implicit casting to generic parameter types (no "generic variance" seems to be the technical term). Not sure I could give you a deeper explanation, but I would just accept it as the way the CLR works...
恐怕没有对泛型参数类型的隐式强制转换(没有“泛型方差”似乎是技术术语)。我不确定我能给你一个更深入的解释,但我接受它作为CLR的工作方式……
You'll simply need to use the Cast extension method on childClassList to cast the list to IEnumerable.
您只需使用childClassList上的Cast扩展方法将列表强制转换为IEnumerable。
#5
0
While in the case of IList and IEnumerable things would work out OK, the compiler has no way of really knowing that when you see it as collection and collection.
虽然对于IList和IEnumerable来说是可以的,但是当您将其视为集合和集合时,编译器无法真正地知道这一点。
If you could use a collection as a collection somebody could try add a Parent to the collection ... the compiler has to prevent this.
如果你可以使用一个集合作为一个集合,有人可以尝试添加一个父元素到集合中……编译器必须防止这种情况。
#1
5
Because generics aren't co/contra variant:
因为泛型不是co/contra变体:
Eric Lippert's blog has a great post on this.
Eric Lippert的博客上有一篇关于这方面的文章。
Another article from Charlie Calvert is here.
Charlie Calvert的另一篇文章在这里。
#2
2
You're missing generic variance, which doesn't exist in C# at the moment. Your code would work in C# 4.0, I believe.
您正在丢失泛型方差,这在c#中是不存在的。我相信您的代码在c# 4.0中可以工作。
This is a duplicate of other questions though...
这是其他问题的重复……
See:
看到的:
- Why can't a
List<string>
be stored in aList<object>
variable -
为什么列表
不能存储在列表 - How does C# 4.0 Generic Covariance and Contra-Variance implemented
- c# 4.0通用协方差和逆变方差如何实现
- Is there a way to cast generic lists to lists of interface/base class types
- 是否有一种方法可以将泛型列表转换为接口/基类类型的列表
- C# .NET passing a collection of InterfaceImplementingClass objects to a routine that takes a collection of Interface objects
- .NET将InterfaceImplementingClass对象的集合传递给一个例程,该例程接受接口对象的集合
- Casting from
IEnumerable<Object>
toIEnumerable<String>
- 从IEnumerable
#3
1
You should find all you're looking for in Eric Lippert's Covariance and Contravariance series. It's a fair bit of reading, but answers (a) why you can't do this in C# 3.0, and (b) why you will be able to do it i C# 4.0.
你应该在Eric Lippert的协方差和逆变级数中找到你要找的所有东西。这是一个很好的阅读材料,但是回答(a)为什么你不能在c# 3.0中这样做,(b)为什么你可以在c# 4.0中这样做。
#4
0
I'm afraid there's no implicit casting to generic parameter types (no "generic variance" seems to be the technical term). Not sure I could give you a deeper explanation, but I would just accept it as the way the CLR works...
恐怕没有对泛型参数类型的隐式强制转换(没有“泛型方差”似乎是技术术语)。我不确定我能给你一个更深入的解释,但我接受它作为CLR的工作方式……
You'll simply need to use the Cast extension method on childClassList to cast the list to IEnumerable.
您只需使用childClassList上的Cast扩展方法将列表强制转换为IEnumerable。
#5
0
While in the case of IList and IEnumerable things would work out OK, the compiler has no way of really knowing that when you see it as collection and collection.
虽然对于IList和IEnumerable来说是可以的,但是当您将其视为集合和集合时,编译器无法真正地知道这一点。
If you could use a collection as a collection somebody could try add a Parent to the collection ... the compiler has to prevent this.
如果你可以使用一个集合作为一个集合,有人可以尝试添加一个父元素到集合中……编译器必须防止这种情况。