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.