![](/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.