There are 4 overloaded signatures for Enumerable.SelectMany. To make it simple, we ignore the two signatures with int argument. So we have 2 signatures for 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
)
My question is: how C# compiler choose SelectMany when translating LINQ expression to extension method invocation?
Basically, if there are multiple from in LINQ expression, there will be SelectMany. But, it seems that C# compiler only choose the second signature. The first signature is never used.
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);
}
With the help of Reflector, I can see that above LINQ expression is translated into
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();
})
Above example involves 3 types. So, it is reasonable to select the second SelectMany signature. However, for below example, only one type is involved, it still selects the second signature.
IEnumerable<int> en4 =
from i1 in en1
from i2 in Enumerable.Range(0, i1)
select i2;
It is translated into:
en1.SelectMany<int, int, int>(delegate (int i1) {
return Enumerable.Range(0, i1);
}, delegate (int i1, int i2) {
return i2;
})
So, I cannot find a case that LINQ expression is translated into the first SelectMany signature. Is there such case?
If the first SelectMany signature is not used, then it exists just because it is BIND of monad in functional programming?
Perhaps the question can be: why do we have 2 signatures of SelectMany?
Thanks.