Enumerable.SelectMany有4個重載簽名。爲了簡單起見,我們忽略了兩個簽名int的說法。因此,我們有2個簽名的SelectMany:C#編譯器在翻譯LINQ表達式時如何選擇SelectMany?
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector
)
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TCollection>> collectionSelector,
Func<TSource, TCollection, TResult> resultSelector
)
我的問題是:如何翻譯LINQ表達式來擴展方法調用時,C#編譯器選擇的SelectMany?
基本上,如果在LINQ表達式中有多個from,將會出現SelectMany。但是,似乎C#編譯器只選擇第二個簽名。第一個簽名從不使用。
IEnumerable<int> en1 = Enumerable.Range(1, 3);
IEnumerable<double> en2 = new double[] { 1.0, 3.14 };
IEnumerable<string> en3 =
from i1 in en1
from i2 in en2
select (i1 * i2).ToString();
foreach (var i in en3)
{
Console.WriteLine(i);
}
隨着反射器的幫助下,我可以看到,上述LINQ表達以上示例涉及3種類型的被轉換成
en1.SelectMany<int, double, string>(delegate (int i1) {
return en2;
}, delegate (int i1, double i2) {
double CS$0$0000 = i1 * i2return CS$0$0000.ToString();
})
。所以,選擇第二個SelectMany簽名是合理的。但是,對於下面的例子,只涉及一種類型,它仍然選擇第二個簽名。
IEnumerable<int> en4 =
from i1 in en1
from i2 in Enumerable.Range(0, i1)
select i2;
它翻譯成:
en1.SelectMany<int, int, int>(delegate (int i1) {
return Enumerable.Range(0, i1);
}, delegate (int i1, int i2) {
return i2;
})
所以,我無法找到的情況下LINQ表達式轉換爲第一署名的SelectMany。有這種情況嗎?
如果沒有使用第一個SelectMany簽名,那麼它的存在只是因爲它在函數式編程中是monad的BIND?
也許問題可能是:爲什麼我們有2個SelectMany簽名?
謝謝。
真的......一個void函數返回一些東西,沒有人對它進行評論? – 2010-07-20 15:49:31