How does the following LINQ statement work?

C#.NetLinq

C# Problem Overview


How does the following LINQ statement work?

Here is my code:

var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
    Console.WriteLine(i);
}

Output: 2, 4, 6, 8

Why not 2, 4, 6?

C# Solutions


Solution 1 - C#

The output is 2,4,6,8 because of deferred execution.

> The query is actually executed when the query variable is iterated over, not when the query variable is created. This is called deferred execution.

> -- Suprotim Agarwal, "Deferred vs Immediate Query Execution in LINQ"

There is another execution called Immediate Query Execution, which is useful for caching query results. From Suprotim Agarwal again:

> To force immediate execution of a query that does not produce a singleton value, you can call the ToList(), ToDictionary(), ToArray(), Count(), Average() or Max() method on a query or query variable. These are called conversion operators which allow you to make a copy/snapshot of the result and access is as many times you want, without the need to re-execute the query.

If you want the output to be 2,4,6, use .ToList():

var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).ToList();
list.Add(8);
foreach (var i in even)
 {
    Console.WriteLine(i);
 }

Solution 2 - C#

This has happened because of deferred execution, which means that the calculation of the expression is not executed until it is needed someplace. This makes the performance better if the data is too large.

Solution 3 - C#

The reason for this is the deferred execution of your lambda expression. The query gets executed when you start iterating in the foreach loop.

Solution 4 - C#

When you use an IEnumerable<> obtained from LINQ, only is created an Enumerator class and the iteration only start when you use it in some walk.

Solution 5 - C#

You are getting this result because of deferred execution which means result is actually not evaluated until its first accessed.

To make it more clear just add 10 to the list at end of your snipet and then print again you will not get 10 in output

     var list = new List<int>{1,2,4,5,6};
    var even = list.Where(m => m%2 == 0).Tolist();
    list.Add(8);
    foreach (var i in even)
    {
        Console.WriteLine(i);
    }
//new*
    list.Add(10);
    foreach (var i in even)
    {
        Console.WriteLine(i);
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2591356View Question on Stackoverflow
Solution 1 - C#Atish DipongkorView Answer on Stackoverflow
Solution 2 - C#Sandeep ChauhanView Answer on Stackoverflow
Solution 3 - C#Prateek DhuperView Answer on Stackoverflow
Solution 4 - C#MiguelView Answer on Stackoverflow
Solution 5 - C#sandeepView Answer on Stackoverflow