linq
Methoden voor het uitvoeren van methoden - onmiddellijke, uitgestelde streaming, uitgestelde niet-streaming
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