Sök…


Uppskjuten utförande kontra omedelbar körning

Vissa LINQ-metoder returnerar ett frågaobjekt. Det här objektet innehåller inte resultaten från frågan. istället har den all information som behövs för att generera dessa resultat:

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

Frågan innehåller ett samtal till Console.Write , men ingenting har matats ut till konsolen. Detta beror på att frågan inte har körts ännu, och därför har funktionen som skickats till Select aldrig utvärderats. Detta kallas uppskjuten exekvering - frågan körs försenas tills någon senare punkt.

Andra LINQ-metoder tvingar en omedelbar exekvering av frågan. dessa metoder kör frågan och genererar dess värden:

var newList = query.ToList();

Vid denna punkt utvärderas funktionen som väljs till Select för varje värde i den ursprungliga listan, och följande kommer att matas ut till konsolen:

1 2 3 4 5


I allmänhet kör LINQ-metoder som returnerar ett enstaka värde (som Max eller Count ) eller som returnerar ett objekt som faktiskt har värdena (som ToList eller ToDictionary ) omedelbart.

Metoder som returnerar ett IEnumerable<T> eller IQueryable<T> returnerar frågaobjektet och gör det möjligt att skjuta upp körningen tills en senare punkt.

Huruvida en viss LINQ-metod tvingar en fråga att exekvera omedelbart eller inte, hittas på MSDN - C # eller VB.NET .

Streaming-läge (lat utvärdering) vs icke-streaming-läge (ivrig utvärdering)

Av LINQ-metoderna som använder uppskjuten exekvering kräver vissa att ett enda värde utvärderas i taget. Följande kod:

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

kommer att mata ut:

3
förut iterationsvärde: 3
5
förhand iterationsvärde: 5
1
förhand iterationsvärde: 1
2
förhand iterationsvärde: 2

eftersom funktionen som skickas till Select utvärderas vid varje iteration av foreach . Detta kallas strömningsläge eller lat utvärdering .


Andra LINQ-metoder - sortering och gruppering av operatörer - kräver att alla värden utvärderas innan de kan returnera något värde:

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

kommer att mata ut:

3
5
1
2
förhand iterationsvärde: 1
förhand iterationsvärde: 2
förut iterationsvärde: 3
förhand iterationsvärde: 5

I det här fallet, eftersom värdena måste genereras till foreach i stigande ordning, måste alla element först utvärderas, för att bestämma vilken som är den minsta, och vilken är den nästa minsta, och så vidare. Detta kallas icke-strömningsläge eller ivrig utvärdering .


Huruvida en viss LINQ-metod använder strömmande eller icke-strömmande läge, kan hittas på MSDN - C # eller VB.NET .

Fördelarna med uppskjuten utförande - byggfrågor

Uppskjuten körning gör det möjligt att kombinera olika operationer för att bygga den slutliga frågan innan värderingen utvärderas:

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

Om vi kör frågan just nu:

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

vi skulle få följande utgång:

2 2 3 4 6 9

Men vi kan ändra frågan genom att lägga till fler operatörer:

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

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

Produktion:

20 20 40 60

Fördelarna med uppskjuten körning - fråga aktuell information

Vid uppskjuten exekvering, om data som ska frågas ändras, använder frågeobjektet data vid tidpunkten för exekvering, inte vid definitionstidpunkten.

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

Om vi kör frågan på denna punkt med en omedelbar metod eller foreach , kommer frågan att fungera på listan med jämna nummer.

Men om vi ändrar värdena i listan:

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

eller även om vi tilldelar en ny lista till data :

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

och sedan köra frågan, kommer frågan att fungera på det nya värdet för data :

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

och kommer att mata ut följande:

1 9 25 49 81



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow