LINQ, deferred execution and closures

Reading Anders’ post on Lexical Closures, Deferred Execution and Kicker Methods with respect to LINQ and Quaere, I thought I would write some notes since VS 2008 is RTM this month and I’ll hopefully get to start doing some more LINQing.

I have used Anders’ example. What result is printed?

int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int i = 1;
var numbersPlusI = from n in numbers
                   select n + i;
i++;
foreach (var n in numbersPlusI) {
  Console.Write(n);
  Console.Write(" ");
}

To make the answer more obvious, let’s rewrite without the layer of syntactic sugar. As I don’t have .NET 3.5 handy on this PC, this is just an approximation built on .NET 2.0:

int[] numbers = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
int i = 1;
IEnumerable<int> numbersPlusI = 
  Enumerable.Select<int>(numbers, delegate(int n) { return n + i; } );
i++;
foreach (int n in numbersPlusI) {
  Console.WriteLine(n);
  Console.Write(" ");
}

LINQ builds up an expression for numbersPlusI, but doesn’t execute it until the result is enumerated. Now remembering that C# has closures, the delegate binds to the local variable i (not its value at the point of declaration). When the enumeration is being performed, the delegate is called using i, which is 2 at the time of execution (i=1; i++). So we get:

2 3 4 5 6 7 8 9 10 11 

If you want to run the code on .NET 2.0, here is my approximation of System.Linq.Enumerable and the Func<> delegate relevant for the example. Probably not brilliant, but I am really aiming to illustrate how variables a captured by closures in C#.

public delegate T Func<T, A>(A a);
public class Enumerable {
  public static IEnumerable<T> Select<T>(IEnumerable<T> source, Func<T,T> valueFromSource) {
    foreach (T value in source) {
      yield return valueFromSource(value);
    }
  }
}

Some good references on this:

Comments