LINQ Deferred Execution–Oops!

A LINQ Tutorial

Deferred execution can be a lifesaver with LINQ but it can have a downside as well.

In this example we set up a LINQ query and then iterate through the results twice. The output may not be quite what we anticipated or want,

int counter = 0;
var evenNumbersInSeries = 
    Enumerable.Range(0, 10).Select(
    x => 
    {
       int result = x + counter;
       counter++;
       return result;
    }
    );

// List the numbers in the series

Console.WriteLine("First Try:\n");
foreach(int i in evenNumbersInSeries) 
{
    Console.WriteLine(i);
}

// List them again

Console.WriteLine("\nSecond Try:\n");
foreach(int i in evenNumbersInSeries) 
{
    Console.WriteLine(i);
}

 

The output for these two runs is shown in the two columns below:

0    10
2    12
4    14
6    16
8    18
10   20
12   22
14   24
16   26
18   28

 

Oops.  The Counter maintained its state, and since we don’t evaluate until the foreach loop, nothing causes the counter to reset.

We could solve this problem in two ways. One is to reset the counter before running the second loop. Another way to solve this is to freeze the evaluation by asking LINQ to convert the results (currently in the variable evenNumberInSeries to an array. The result would be that the entire series would be evaluated and placed in the array and then we’d iterate through the array:

int counter = 0;
var evenNumbersInSeries = 
    Enumerable.Range(0, 10).Select(
    x => 
    {
       int result = x + counter;
       counter++;
       return result;
    }
    ).ToArray();


Console.WriteLine("First Try:\n");
foreach(int i in evenNumbersInSeries) 
{
    Console.WriteLine(i);
}


Console.WriteLine("\nSecond Try:\n");
foreach(int i in evenNumbersInSeries) 
{
    Console.WriteLine(i);
}

 

Because ToArray forces the results into an array, the entire series is evaluated before the foreach loops run, and the foreach loops iterate over the array. The array has the (unchanging) results and so the two itereations are identical,

0   0
2   2
4   4
6   6
8   8
10  10
12  12
14  14
16  16
18  18

About Jesse Liberty

Jesse Liberty is an independent consultant and programmer with three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP, Microsoft MVP and Telerik MVP.
This entry was posted in Data, Linq, Mini-Tutorial and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *