LINQ: Deferred Execution

Another interesting tidbit I learned about at the summit was deferred execution of LINQ queries.

Here's an example that highlights what deferred execution means to you.   Let's create a Customer class and then build up a list of customers:

   1: public class Customer
   2: {
   3:     public int ID { get; set; }
   4:     public string Name { get; set; }
   5:     public double Balance { get; set; }
   6: }
   1: static List<Customer> GetCustomers()
   2: {
   3:     return new List<Customer>()
   4:     {
   5:         new Customer {ID = 1, Name="Bill", Balance = 22.50},
   6:         new Customer {ID = 2, Name="Bob", Balance = 0.00},
   7:         new Customer {ID = 3, Name="Joe", Balance = -5.00}
   8:     };
   9: }

Now assume we're going to run a query to find all Customers whose first name begins with a particular letter (supplied in a variable):

   1: var customers = GetCustomers();
   2:  
   3: string firstLetter = "B";
   4: var query = from c in customers
   5:             where c.Name.StartsWith(firstLetter)
   6:             select c;
   7:  
   8: firstLetter = "J";
   9: foreach (Customer c in query)
  10: {
  11:     Console.WriteLine(c.Name);
  12: }

What do you think prints out?  Due to deferred execution, the application will only print "Joe", not "Bill" and "Bob" as you might expect.

The code executed in line 4 only builds the query into a query expression tree.  And that expression tree includes a reference to the "firstLetter" variable, not its contents.  The expression tree is not executed until line 9 when a foreach loop is used.  As a result, the value of the "firstLetter" variable is not obtained until line 9.

So be careful how you use locally-scoped variables in your LINQ queries and be aware of deferred execution in LINQ queries.

1 Comment

Comments have been disabled for this content.