CODE LAB: C# ToList() - ToRemember()

Avoid Deferred Execution While Writing LINQ Queries

LINQ makes querying of data so much easier than for/each loops with nested if blocks and other conditional logic. But remember that all of that fancy LINQ stuff is simply syntactic sugar over method calls.

Consider this simple example of a method using LINQ-to-SQL to get a list of customers:

										
public IEnumerable
		GetCustomers()
		{
		using(var context = new DBContext())
		{
		return from c in context.Customers
		where c.Balance > 2000
		select c;
		}
}
												
														

Seems pretty harmless -- until you get an "ObjectDisposedException" when you try and enumerate the collection. Why? Because LINQ doesn't actually perform the query until you try and enumerate the results. The DBContext class (which exposes the Customers collection) is disposed of when this call exits. Once you try and enumerate through the collection, the DBContext.Customers class is referenced and you get the exception.

A simpler example:

										
decimal minimumBalance = 500;
var customersOver500 = from c in customers
where c.Balance > minimumBalance select c;

minimumBalance = 200;
var customersOver200 = from c in customers
where c.Balance > minimumBalance select c;

int count1 = customersOver500.Count();
int count2 = customersOver200.Count();
												
														

Suppose we have four customers with the following balances: 100, 300, 400 and 600. What will count1 and count2 be? They'll both be 3. The "customersOver500" references the "minimumBalance" variable, but the value isn't obtained until the query results are iterated over (through a for/each loop, a ToList() call or even a "Count()" call as shown above). At the time the value is used to process the query, the value for minimumBalance has already changed to 200, so both LINQ queries produce identical results (customers with a balance over 200).

If you have cases where you want to ensure your LINQ queries are evaluated right away, convert them to a List via ToList(), or to an array via ToArray().

* Disclaimer. Since free code is available out there on the internet, and so many people have written up about the use of it I decided to use some examples from a source I trust. And in this line I would like to thank them and everyone else that shares there code, for this and reference them in this regard.