C#: Anonymous methods are not closures

<Edit: See the extended discussion at the end of which I conclude Anonymous methods are indeed lexical closures!!! >

Anonymous methods in C# are just anonymous methods and do not represent true lexical closure. There are a lot of samples and code out there explaining why. I use a simple example in my mind to remember why it is not the same.

First lets see how the sample works in a language like Ruby which implements true lexical closure.

 $arr = Array.new# function funcGen fills the array arr with generated # functions (closures) that print an integer i. i varies # from 0 to val (10) when the function is generateddef funcGen(val)    0.upto(val) do |i|         # same as for(i=0;i<val;i++)        $arr[i] = Proc.new {   # Proc.new creates the closure                    print i    # body of the closure                    print ' '                  }    endendfuncGen(10) # call funcGen to fill the array
# each function in the array arr is called to print# the value of i$arr.each do |val|    val.callend

Definition of closure requires that the lexical state of the closure when it's created is preserved. So all the variables (environment) used by the closure at the timeof  its creation should be captured at a point in time. Since Ruby implementes true closure and it does this the result of running the above code is

0 1 2 3 4 5 6 7 8 9 10

If we see the same sample in C# it'll be some thing like

 using System;namespace AnonymousMethod{    delegate void Func();    class Program    {        static Func[] funcArr = new Func[10];        static void fillFunc(int count)        {            for (int i = 0; i < count; i++)            {                funcArr[i] = delegate()                             {                                Console.Write("{0} ", i);                             };            }        }        static void Main(string[] args)        {            fillFunc(funcArr.Length);            for (int i = 0; i < funcArr.Length; i++)            {                funcArr[i]();            }        }    }}

However, even though the same logic as in Ruby is implemented in this C# code the result is totally different and is

10 10 10 10 10 10 10 10 10 10

So in this case the value of i when the anonymous method was created is NOT used and the last modified value of i is used. This clearly indicates that lexical environment of all these methods are not closed. In anonymous methods these read-only variables are shared between the outer method and all the other anonymous mehtods. This sample can be tweaked a little to get it to match that of Ruby. The modified sample is as below with all changes marked in bold

 using System;namespace AnonymousMethod{    delegate void Func();    class Program    {        static Func[] funcArr = new Func[10];        static void fillFunc(int count)        {            for (int i = 0; i < count; i++)            {                int j = i;                 funcArr[i] = delegate()                             {                                Console.Write("{0} ", j);                             };            }        }        static void Main(string[] args)        {            fillFunc(funcArr.Length);            for (int i = 0; i < funcArr.Length; i++)            {                funcArr[i]();            }        }    }}

With this change in code the output will get changed and will be the same as the Ruby program (0 1 2 3 4 5 6 7 8 9). The difference in the result further strengthens the fact that true closure is not implemented by C#. Inspection of the generated assembly with Reflector clearly shows why...

In either case to encapsulate the anoymous method and the variable i it referes to the compiler generates a class

 [CompilerGenerated]private sealed class <>c__DisplayClass2{    public <>c__DisplayClass2();    publicvoid  <fillFunc>b__0()      {        Console.Write(  "{0} ", this .i);      }     public int i;}

The method in bold is the anonymous method.

In the first case while parsing the fillFunc method the compiler sees the following code

 for (int i = 0; i < count; i++){    funcArr[i] = delegate()                 {                     Console.Write("{0} ", i);                 };}

and figures out that a variable i from the outer scope is used by the anonymous method and the compiler emits the following code

 private static void fillFunc(int count){    Func func1 = null;    Program .<>c__DisplayClass2 class1 = newProgram .<>c__DisplayClass2();     class1.i = 0;     while (class1.i < count)    {       if (func1 == null)       {          func1 = new Func(class1.<fillFunc>b__0);       }       Program.funcArr[class1.i] = func1;       class1.i++;     }}

It is obvious from this code that only one object class1 of the generated class is created and is shared between all the anonymous methods and the loop generating the methods. So if anyone of the methods are called later, the last modified value of i (= 10) will be returned.

For the second case on seeing

 static void fillFunc(int count){    for (int i = 0; i < count; i++)    {        int j = i;         funcArr[i] = delegate()                     {                         Console.Write("{0} ", j);                     };    }}

The compiler generates the following code

 private static void fillFunc(int count){    for (int num1 = 0; num1 < count; num1++)    {        Program.<>c__DisplayClass1 class1 =  new Program.<>c__DisplayClass1();         class1.j = num1;         Program.funcArr[num1] = new Func(class1.<fillFunc>b__0);    }}

Here the class used to encapsulate the anonymous method is very similiar to the one used in the first case. However, since the method uses a variable inside the loop, for each iteration a new object is created. This results is each anonymous methods having its own copy of the object and hence the value of j in it is same as it was at the time of the method creation.