Frage Ist Select gefolgt von Wo ergeben sich zwei Iterationen über IEnumerable?


Lass es mich sagen

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = list.Select(item => item * 10).Where(item => item < 20).ToList();

Die Frage ist, gibt es zwei Iterationen oder nur eine.

Mit anderen Worten, entspricht das der Leistung:

IEnumerable<int> list = new int[] { 1, 2, 3 };
List<int> filtered = new List<int>();
foreach(int item in list) {
    int newItem = item * 10;
    if(newItem < 20)
        filtered.Add(newItem);
}

5
2017-11-02 22:34


Ursprung


Antworten:


Es gibt eine einzige Iteration über die Sammlung, die beim Aufruf von .ToArray Methode so beide sollten gleichwertig sein. .Select ist eine Projektion und .Where ist ein Filter, beide ausgedrückt als Ausdrucksbäume auf dem ursprünglichen Dataset.

Konnte leicht bewiesen werden:

public class Foo: IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 1;
        Console.WriteLine("we are at element 1");
        yield return 2;
        Console.WriteLine("we are at element 2");
        yield return 3;
        Console.WriteLine("we are at element 3");
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main()
    {
        var filtered = new Foo()
            .Select(item => item * 10)
            .Where(item => item < 20)
            .ToList();
    }
}

Wenn run gedruckt wird, folgt Folgendes:

we are at element 1
we are at element 2
we are at element 3

7
2017-11-02 22:43



In Linq to Objects WHERE und SELECT iterieren nicht über das Aufzählungszeichen. Der aufrufende Code listet es auf, wenn es eine Foreach für die Abfrage oder ToList oder ToArray () usw. ausführt.

In Linq to SQL gibt es keine Iteration was auch immer. Wenn Sie ToList oder ToArray () ausführen, wird die Abfrage von der Datenbank ausgeführt. Abhängig vom Abfragetyp kann die Datenbank nach Indizes suchen oder einen Tabellenscan durchführen.


2
2017-11-02 23:00