2009-01-08 58 views
9

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簽名?

謝謝。

回答

5

根據C#Spec,編譯器不會生成對SelectMany的第一個版本的重載調用。 SelectMany的第一個版本對於將List列表展平爲單個平面列表非常有用。

public IEnumerable<string> Example(IEnumerable<IEnumerable<string>> enumerable) { 
    return enumerable.SelectMany(x => x); 
} 

它在查詢表達式中沒有很強的等價性。

有關更多信息,請參見C#語言規範的第7.15.2節。

+1

真的......一個void函數返回一些東西,沒有人對它進行評論? – 2010-07-20 15:49:31

5

爲什麼我們有2個SelectMany簽名?

所以我可以在我的代碼中使用第一個。

var orders = Customers.SelectMany(c => c.Orders) 
+0

當然。這只是爲了方便。 – 2009-11-18 19:07:34