Frage

Es gibt 4 überlastet Unterschriften für Enumerable.SelectMany. Um es einfach zu machen, ignorieren wir die beiden Signaturen mit int Argument. So haben wir 2 Unterschriften für Select:

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
)

Meine Frage ist: wie C # -Compiler Select wählen, wenn LINQ Ausdruck Erweiterung Methodenaufruf übersetzen

?

Im Grunde genommen, wenn es mehrere sind in LINQ Ausdruck, wird es Select sein. Aber, so scheint es, dass C # Compiler nur die zweite Signatur wählen. Die erste Signatur wird nie verwendet.

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

Mit Hilfe von Reflektor, kann ich über LINQ Ausdruck, dass in

übersetzt
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();
    })

Im obigen Beispiel beinhaltet drei Arten. So ist es sinnvoll, die zweite Select Signatur auszuwählen. Doch für unter Beispiel nur eine Art beteiligt ist, wählt er immer noch die zweite Unterschrift.

        IEnumerable<int> en4 =
            from i1 in en1
            from i2 in Enumerable.Range(0, i1)
            select i2;

Es wird übersetzt in:

en1.SelectMany<int, int, int>(delegate (int i1) {
        return Enumerable.Range(0, i1);
    }, delegate (int i1, int i2) {
        return i2;
    })

Also, ich kann nicht einen Fall feststellen, dass LINQ-Ausdruck in die erste Select Signatur übersetzt. Gibt es einen solchen Fall?

Wenn die erste Select Signatur nicht verwendet wird, dann ist es existiert nur, weil es BIND von Monade in der funktionalen Programmierung ist?

Vielleicht kann die Frage sein: warum haben wir zwei Unterschriften von Select

Danke.

War es hilfreich?

Lösung

Nach dem C # Spec, wird der Compiler nicht eine Überlastung Aufruf an die erste Version von Select erzeugen. Die erste Version von Select ist nützlich, um eine Liste der Listen in eine einzige flache Liste Abflachung.

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

Es ist nicht ein starkes äquivalent in einem Abfrageausdruck hat.

Siehe Abschnitt 7.15.2 der Sprache C # Spec für weitere Informationen.

Andere Tipps

  

warum haben wir zwei Unterschriften von Select?

So kann ich die ersten in meinem Code verwenden.

var orders = Customers.SelectMany(c => c.Orders)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top