Zoeken…


Uitgestelde uitvoering versus onmiddellijke uitvoering

Sommige LINQ-methoden retourneren een queryobject. Dit object bevat niet de resultaten van de zoekopdracht; in plaats daarvan heeft het alle informatie die nodig is om die resultaten te genereren:

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

De query bevat een aanroep naar Console.Write , maar er is niets naar de console uitgevoerd. De reden hiervoor is dat de query nog niet is uitgevoerd en dat de functie die aan Select is doorgegeven nooit is geëvalueerd. Dit staat bekend als uitgestelde uitvoering - de uitvoering van de query wordt uitgesteld tot een later punt.

Andere LINQ-methoden dwingen een onmiddellijke uitvoering van de query; deze methoden voeren de query uit en genereren de waarden:

var newList = query.ToList();

Op dit punt wordt de functie die is doorgegeven aan Select geëvalueerd voor elke waarde in de oorspronkelijke lijst en het volgende wordt uitgevoerd naar de console:

1 2 3 4 5


Over het algemeen worden LINQ-methoden die een enkele waarde retourneren (zoals Max of Count ) of die een object retourneren dat de waarden bevat (zoals ToList of ToDictionary ) onmiddellijk uitgevoerd.

Methoden die een IEnumerable<T> of IQueryable<T> retourneren, retourneren het IQueryable<T> en laten toe de uitvoering tot een later punt uit te stellen.

Of een bepaalde LINQ-methode een zoekopdracht dwingt om onmiddellijk uit te voeren of niet, is te vinden op MSDN - C # of VB.NET .

Streaming-modus (luie evaluatie) versus niet-streaming-modus (enthousiaste evaluatie)

Van de LINQ-methoden die uitgestelde uitvoering gebruiken, vereisen sommige dat één waarde per keer wordt geëvalueerd. De volgende 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}");
}

zal uitvoeren:

3
voor elke iteratiewaarde: 3
5
voor elke iteratiewaarde: 5
1
voor elke iteratiewaarde: 1
2
voor elke iteratiewaarde: 2

omdat de aan Select doorgegeven functie wordt geëvalueerd bij elke iteratie van de foreach . Dit staat bekend als streaming-modus of luie evaluatie .


Andere LINQ-methoden - sorteer- en groepeeroperatoren - vereisen dat alle waarden worden geëvalueerd voordat ze een waarde kunnen retourneren:

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

zal uitvoeren:

3
5
1
2
voor elke iteratiewaarde: 1
voor elke iteratiewaarde: 2
voor elke iteratiewaarde: 3
voor elke iteratiewaarde: 5

In dit geval, omdat de waarden in oplopende volgorde naar de foreach moeten worden gegenereerd, moeten alle elementen eerst worden geëvalueerd om te bepalen welke de kleinste is en welke de volgende kleinste is, enzovoort. Dit staat bekend als niet-streamingmodus of enthousiaste evaluatie .


Of een bepaalde LINQ-methode streaming of niet-streaming gebruikt, is te vinden op MSDN - C # of VB.NET .

Voordelen van uitgestelde uitvoering - vragen bouwen

Uitgestelde uitvoering maakt het combineren van verschillende bewerkingen mogelijk om de laatste query samen te stellen, voordat de waarden worden geëvalueerd:

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

Als we de query op dit punt uitvoeren:

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

we zouden de volgende output krijgen:

2 2 3 4 6 9

Maar we kunnen de zoekopdracht wijzigen door meer operators toe te voegen:

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

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

Output:

20 20 40 60

Voordelen van uitgestelde uitvoering - opvragen van huidige gegevens

Als de uit te voeren gegevens bij uitgestelde uitvoering worden gewijzigd, gebruikt het queryobject de gegevens op het moment van uitvoering, niet op het moment van definitie.

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

Als we de query op dit punt uitvoeren met een directe methode of foreach , wordt de query uitgevoerd op de lijst met even getallen.

Als we de waarden in de lijst echter wijzigen:

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

of zelfs als we een nieuwe lijst aan data toewijzen:

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

en voer vervolgens de query uit, de query werkt op de nieuwe waarde van data :

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

en zal het volgende uitvoeren:

1 9 25 49 81



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow