![](/img/trans.png)
[英]How can I reduce IEnumerable<IEnumerable<Foo>> to IEnumerable<Foo>?
[英]Why can't I pass a List<List<Foo>> to an IEnumerable<IEnumerable<Foo>>
此代码生成两个编译时错误:
private void DoSomething()
{
List<List<Foo>> myFoos = GetFoos();
UseFoos(myFoos);
}
private void UseFoos(IEnumerable<IEnumerable<Foo>>)
{
}
The best overloaded method match for 'NameSpace.Class.UseFoos(System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<Foo>>)' has some invalid arguments
和
Argument 1: cannot convert from 'System.Collections.Generic.List<System.Collections.Generic.List<Foo>>' to 'System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<Foo>>'
转换为IEnumberable<List<Foo>>
不是问题。 如何转换它失败的类型的内部List
组件有什么不同?
编辑:我刚刚意识到我还没有真正回答如何解决限制的问题。 幸运的是,这很容易:
UseFoos(myFoos.Cast<IEnumerable<Foo>>());
该代码在C#4下编译得很好(当你给出了UseFoos
参数一个名字时),它引入了接口和委托的通用协方差和逆变 。
作为一个更简单的例子,这适用于C#4,但不适用于C#3:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
请注意,即使在C#4中,类也不是不变的,所以这不起作用:
// This won't work
List<string> strings = new List<string>();
List<object> objects = strings;
......甚至对于接口,只有在安全的情况下才支持它:
// This won't work either
IList<string> strings = new List<string>();
IList<object> objects = strings;
接口(或委托)必须声明类型参数本身的方差,因此如果您查看IEnumerable<T>
的.NET 4 文档,您将看到它被声明为
public interface IEnumerable<out T>
其中, out
声明的协方差T
。
埃里克利珀有很多在他的博客类别详细了解此协方差和逆变 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.