linq Streaming mode (lazy evaluation) vs non-streaming mode (eager evaluation)


Example

Of the LINQ methods which use deferred execution, some require a single value to be evaluated at a time. The following 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}");
}

will output:

3
foreach iteration value: 3
5
foreach iteration value: 5
1
foreach iteration value: 1
2
foreach iteration value: 2

because the function passed to Select is evaluated at each iteration of the foreach. This is known as streaming mode or lazy evaluation.


Other LINQ methods -- sorting and grouping operators -- require all the values to be evaluated, before they can return any value:

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

will output:

3
5
1
2
foreach iteration value: 1
foreach iteration value: 2
foreach iteration value: 3
foreach iteration value: 5

In this case, because the values must be generated to the foreach in ascending order, all the elements must first be evaluated, in order to determine which is the smallest, and which is the next smallest, and so on. This is known as non-streaming mode or eager evaluation.


Whether a particular LINQ method uses streaming or non-streaming mode, can be found at MSDN -- C#, or VB.NET.