Suche…


Verschobene Ausführung vs. sofortige Ausführung

Einige LINQ-Methoden geben ein Abfrageobjekt zurück. Dieses Objekt enthält nicht die Ergebnisse der Abfrage. Stattdessen verfügt er über alle Informationen, um diese Ergebnisse zu generieren:

var list = new List<int>() {1, 2, 3, 4, 5};
var query = list.Select(x => {
    Console.Write($"{x} ");
    return x;
});

Die Abfrage enthält einen Aufruf von Console.Write , es wurde jedoch nichts an die Konsole ausgegeben. Dies liegt daran, dass die Abfrage noch nicht ausgeführt wurde und daher die an Select Funktion noch nie ausgewertet wurde. Dies wird als verzögerte Ausführung bezeichnet - die Ausführung der Abfrage wird bis zu einem späteren Zeitpunkt verzögert.

Andere LINQ-Methoden erzwingen eine sofortige Ausführung der Abfrage. Diese Methoden führen die Abfrage aus und generieren ihre Werte:

var newList = query.ToList();

An diesem Punkt wird die an Select Funktion für jeden Wert in der ursprünglichen Liste ausgewertet, und Folgendes wird an die Konsole ausgegeben:

1 2 3 4 5


Im Allgemeinen werden LINQ-Methoden, die einen einzelnen Wert zurückgeben (z. B. Max oder Count ) oder ein Objekt zurückgeben, das die Werte tatsächlich enthält (z. B. ToList oder ToDictionary ), sofort ausgeführt.

Methoden, die ein IEnumerable<T> oder IQueryable<T> zurückgeben, geben das Abfrageobjekt zurück und ermöglichen die Zurückstellung der Ausführung bis zu einem späteren Zeitpunkt.

Ob eine bestimmte LINQ-Methode die sofortige Ausführung einer Abfrage erzwingt oder nicht, finden Sie unter MSDN- C # oder VB.NET .

Streaming-Modus (Lazy Evaluation) vs. Nicht-Streaming-Modus (eifrige Auswertung)

Bei einigen LINQ-Methoden, die die verzögerte Ausführung verwenden, muss bei jedem Wert ein einzelner Wert ausgewertet werden. Der folgende Code:

var lst = new List<int>() {3, 5, 1, 2};
var streamingQuery = lst.Select(x => {
    Console.WriteLine(x);
    return x;
});
foreach (var i in streamingQuery) {
    Console.WriteLine($"foreach iteration value: {i}");
}

wird ausgeben:

3
für jeden Iterationswert: 3
5
für jeden Iterationswert: 5
1
für jeden Iterationswert: 1
2
für jeden Iterationswert: 2

weil die an Select Funktion bei jeder Iteration des foreach ausgewertet wird. Dies wird als Streaming-Modus oder Lazy-Evaluation bezeichnet .


Bei anderen LINQ-Methoden - Sortier- und Gruppierungsoperatoren - müssen alle Werte ausgewertet werden, bevor sie einen Wert zurückgeben können:

var nonStreamingQuery = lst.OrderBy(x => {
    Console.WriteLine(x);
    return x;
});
foreach (var i in nonStreamingQuery) {
    Console.WriteLine($"foreach iteration value: {i}");
}

wird ausgeben:

3
5
1
2
für jeden Iterationswert: 1
für jeden Iterationswert: 2
für jeden Iterationswert: 3
für jeden Iterationswert: 5

Da in diesem Fall die Werte in aufsteigender Reihenfolge für das foreach generiert werden müssen, müssen zuerst alle Elemente ausgewertet werden, um zu bestimmen, welches das kleinste ist und welches das nächstkleinste ist usw. Dies wird als Nicht-Streaming-Modus oder eifrige Auswertung bezeichnet .


Ob eine bestimmte LINQ-Methode Streaming- oder Nicht-Streaming-Modus verwendet, finden Sie unter MSDN- C # oder VB.NET .

Vorteile der verzögerten Ausführung - Abfragen erstellen

Durch die verzögerte Ausführung können verschiedene Vorgänge kombiniert werden, um die endgültige Abfrage zu erstellen, bevor die Werte ausgewertet werden:

var list = new List<int>() {1,1,2,3,5,8};
var query = list.Select(x => x + 1);

Wenn wir die Abfrage an dieser Stelle ausführen:

foreach (var x in query) {
    Console.Write($"{x} ");
}

wir würden die folgende Ausgabe erhalten:

2 2 3 4 6 9

Wir können die Abfrage jedoch ändern, indem Sie weitere Operatoren hinzufügen:

Console.WriteLine();
query = query.Where(x => x % 2 == 0);
query = query.Select(x => x * 10);

foreach (var x in query) {
    Console.Write($"{x} ");
}

Ausgabe:

20 20 40 60

Vorteile der verzögerten Ausführung - Abfrage der aktuellen Daten

Wenn die abzufragenden Daten geändert werden, verwendet das Abfrageobjekt die Daten zum Zeitpunkt der Ausführung, nicht zum Zeitpunkt der Definition.

var data = new List<int>() {2, 4, 6, 8};
var query = data.Select(x => x * x);

Wenn wir die Abfrage zu diesem Zeitpunkt mit einer unmittelbaren Methode oder foreach ausführen, foreach die Abfrage die Liste der geraden Zahlen.

Wenn wir jedoch die Werte in der Liste ändern:

data.Clear();
data.AddRange(new [] {1, 3, 5, 7, 9});

oder auch wenn wir den data neue Liste zuweisen:

data = new List<int>() {1, 3, 5, 7, 9};

und führen Sie dann die Abfrage aus. Die Abfrage bearbeitet den neuen Wert der data :

foreach (var x in query) {
    Console.Write($"{x} ");
}

und gibt folgendes aus:

1 9 25 49 81



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow