Pregunta

Hay 4 firmas sobrecargadas para Enumerable.SelectMany. Para hacerlo simple, ignoramos las dos firmas con el argumento int . Así que tenemos 2 firmas para 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
)

Mi pregunta es: ¿cómo el compilador de C # elige SelectMany al traducir la expresión LINQ a la invocación del método de extensión?

Básicamente, si hay varios de en la expresión LINQ, habrá SelectMany. Pero, parece que el compilador de C # solo elige la segunda firma. La primera firma nunca se usa.

        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);
        }

Con la ayuda de Reflector, puedo ver que la expresión de LINQ anterior se traduce a

en1.SelectMany<int, double, string>(delegate (int i1) {
        return en2;
    }, delegate (int i1, double i2) {
        double CS
        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;
    })
= i1 * i2return CS<*><*>.ToString(); })

El ejemplo anterior involucra 3 tipos. Por lo tanto, es razonable seleccionar la segunda firma de SelectMany. Sin embargo, para el siguiente ejemplo, solo hay un tipo involucrado, aún así selecciona la segunda firma. <*>

Está traducido a:

<*>

Por lo tanto, no puedo encontrar un caso en el que la expresión LINQ se traduzca en la primera firma de SelectMany. ¿Existe tal caso?

Si la primera firma de SelectMany no se usa, entonces existe solo porque es una CLASE de mónada en la programación funcional.

Quizás la pregunta puede ser: ¿por qué tenemos 2 firmas de SelectMany?

Gracias.

¿Fue útil?

Solución

De acuerdo con la especificación de C #, el compilador no generará una llamada de sobrecarga a la primera versión de SelectMany. La primera versión de SelectMany es útil para aplanar una Lista de listas en una sola lista plana.

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

No tiene un equivalente fuerte en una expresión de consulta.

Consulte la Sección 7.15.2 de la especificación del lenguaje C # para obtener más información.

Otros consejos

  

¿Por qué tenemos 2 firmas de SelectMany?

Así que puedo usar el primero en mi código.

var orders = Customers.SelectMany(c => c.Orders)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top