Share via


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.

Comments

  • Anonymous
    October 17, 2005
    Actually, this demonstrates why C# does have true lexical closure. In the first C# example, i has a single lexical binding during definition of all the functions, and they all share that one binding, so they all print its current value.

    Similar Common Lisp code (using a list instead of an array) looks like this:

    (setq arr (loop for i upto 10 collect #'(lambda () (format t "~A " i))))

    (loop for val in arr (apply val))

    The output is:
    11 11 11 11 11 11 11 11 11 11 11

    Note that in your examples, the Ruby example creates 11 functions, while the C# creates 10. This Lisp example creates 11.

    In your second C# example, j is introduced as a name binding in the loop body; thus a different binding is seen by each created function. This is exactly as expected with lexical closure.

    Ruby has odd rules with respect to the lexical binding of names. Since i is not defined before the loop, the i in the loop acts like a parameter to the loop body, which means that it is bound anew on each iteration. If you simply add the statement "i = 0" before the loop, i is now lexically bound outside the loop, and you get results similar to the C# case (except you'll print tens instead of elevenses, due to the fencepost error in your examples).

  • Anonymous
    October 18, 2005
    If you change funcGen to

    def funcGen(val)
    for i in 0..val
    $arr[i] = Proc.new {
    print i
    print ' '
    }
    end
    end

    you will get the same behavior as in C#.

  • Anonymous
    October 18, 2005
    C# implements true closures...

    The ruby example that you showed does not demonstrate lexical closure, because i is being used as a parameter. The ruby is more analogous to calling the following C# function.

    public void UpTo(int start, int end, ToAction<int> func)
    {
    for (int i=start; i<=end; i++)
    func(i);
    }

    In this case, this makes it clear that i is a parameter to a function.

  • Anonymous
    October 18, 2005
    I'm a bit confused... First you show an example of closures. Then a couple steps later you show an example of how to get the exact same result from C#, but conclude that C# doesn't have closures?

    Quite frankly, closures wouldn't be terribly useful if they could only capture the value of a variable at the time of its instantiation. You'd end up with an implementation of Java's inner classes.

  • Anonymous
    October 18, 2005
    To clarify Gabe, what I tried to show was that if C# did implement true closure then in either case the same result should have been obtained and tweaking to get the desired effect would have not been required.

    Definitions of Lexical closures seem to vary and so does the opinion on whether C# implements closure. To quote Brad Adams (http://blogs.msdn.com/brada/archive/2004/08/03/207164.aspx) "Anonymous methods are not closures or completions. They are anonymous methods. They allow sharing of variables with the outer method (not copy in, or copy out, or copy in-out, or even by ref) "

    In one definition of closure from the C2 wiki is that "In proper closures, not just the value is kept, but a reference to the actual object passed in". In this case C# does implement closure.

    Again in another definition "during the creation of the closure the lexical environment is captured". In C# since changes made in child scope propagate to the parent scope and to all other closures it does not implement closure.

  • Anonymous
    October 19, 2005
    The discussions in that other blog are somewhat confused, and the
    C2 page is not as clear as it could be.

    The context that code runs in consists of mappings of names to
    things, most notably (in this case) to variables. A variable is
    any location where you can store a value (a value, usually, an
    object reference in C#). It is this name/variable (not
    name/value) mapping that is at issue in closures.

    In a language with lexical scoping (which is to say, most
    languages nowadays), the lexical enclosing scope of some code
    determines the name/variable mappings. A local variable name
    defined (or 'bound'. to use Lisp terminology) in a method will
    refer to a different, unique variable each time the method is
    called, even though it's the same name and the same code that
    references it.

    When you create a closure, you're creating a function that
    'closes over' its lexical environment as it exists when the
    closure is created. This means that the name/variable bindings
    that are active at the time the closure is created continue to
    exist for that closure. If other closures are created (e.g. the
    ten (or eleven) closures in your examples) in the same lexical
    environment, they then share the same name/variable mappings. But
    note that the same lexical scope, invoked multiple times, can
    produce distinct bindings. Each such environment is a distinct
    lexical environment.

    Even the definition of closure on
    wikipedia (http://en.wikipedia.org/wiki/Lexical_closure) is a bit
    weak because it talks about name/value mappings, not
    name/variable mappings. But see the notes about 'delay
    evaluation' and 'multiple functions'. (BTW, learning Lisp helped
    me immensely in fine-tuning my understanding of environments,
    bindings, the distinctions between variables and names, variable
    lifetimes, and other fundamental programming language isssues.)

    To really appreciate this, you need examples that show the
    mutability and shared nature of the variables from the lexical
    environment, as well as how the variables are distinct when they
    come from different invocations of the lexical
    environment. Here's an example in Ruby.

    -----------------
    $printers = Array.new
    $setters = Array.new

    # Function funcGen creates two lexical closures each time it's called;
    # one setter and one printer. These two functions share a
    # lexically-scoped variable referred to by num that is unique to these
    # two functions.
    def funcGen()
    # We get a new binding of num to a unique variable each time we get
    # here.
    num = 0
    $printers.push(Proc.new {
    print num
    print ' '
    })
    $setters.push(Proc.new {|new_num|
    # Change the value of num.
    num = new_num})
    end

    # Generate ten setter/getter pairs.
    0.upto(9) {
    funcGen()
    }

    # Initially, all the printers will print zero.
    $printers.each do |f|
    f.call
    end
    puts

    # Tell each setter to modify its shared variable.
    0.upto(9) do |i|
    $setters[i].call(i+1)
    end

    # Each printer should print a different value now.
    $printers.each do |f|
    f.call
    end
    -----------------

    Here's similar code in lisp.

    -----------------
    (defparameter setters nil)
    (defparameter printers nil)

    (defun genFun ()
    (let ((num 0))
    (push #'(lambda (new_num) (setq num new_num)) setters)
    (push #'(lambda () (format t "~A " num)) printers)))

    ; Generate ten setter/getter pairs.
    (dotimes (i 10)
    (genFun))

    ; Initially, all the printers will print zero.
    (format t "~%")
    (loop for val in printers
    do (apply val nil))

    ; Tell each setter to modify its shared variable.
    (loop
    for val in setters
    for i upfrom 0
    do (apply val (+ i 1) nil))

    ; Each printer should print a different value now.
    (format t "~%")
    (loop for val in printers
    do (apply val nil))
    -----------------

    Anyone care to try a C# version to test the closures there?

  • Anonymous
    October 20, 2005
    class Program
    {
    delegate void Func();
    delegate void PrintersFunc();
    delegate void SettersFunc(int new_num);

    static List<PrintersFunc> printers = new List<PrintersFunc>();
    static List<SettersFunc> setters = new List<SettersFunc>();

    static void FuncGen()
    {
    int num = 0;
    printers.Add(delegate()
    {
    Console.Write(num);
    Console.Write(' ');
    });

    setters.Add(delegate(int new_num)
    {
    num = new_num;
    });
    }

    static void Main(string[] args)
    {
    for (int i = 0; i < 10; i++)
    {
    FuncGen();
    }

    foreach (PrintersFunc p in printers)
    {
    p();
    }

    for (int i = 0; i < 10; i++)
    {
    setters[i](i + 1);
    }

    foreach (PrintersFunc p in printers)
    {
    p();
    }

    // if the output was suppose to be similar to:
    // 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10
    // then this code follows the same behavior.
    }
    }

  • Anonymous
    October 20, 2005
    Yes, James, that's the expected output. Sorry that I forgot to include it with my examples.

    In the discussion of BradA's referenced blog, Ian Griffiths asks the right question, and the answer is that the sharing of lexical variables, not just values, is expected of closures. This is the definition that Lisp has used since long before Ruby or C# existed.

    The only sense in which anonymous methods could be considered different from closures is that they are methods rather than functions. But this is a fairly trivial difference. In essence, the implicit 'this' variable is just another lexical variable that is captured in the closure.

  • Anonymous
    October 20, 2005
    I interpreted the definition of lexical closure is to share values not variables. In case it is sharing of variables then C# does implement lexical closure. This brings up an interesting thought, why do people in the C# team including BradA and Eric always say that anonymous methods are not closures?

    Anyways, all these discussions sooner or later lead to Lisp/Scheme/Ruby. I guess I have to start on Lisp soon.....

  • Anonymous
    October 21, 2005
    abhinaba: That's indeed a good question. If I had to guess based on that other blog, I'd say BradA is relying on C2 and wikipedia for definitions. Not an unreasonable notion, but it happens to fail in this instance. I think the Common Lisp definition is arguably a better choice due to its age.

    You might consider drawing their attention to this exchange to see what they have to say.

    As I understand it, ML, being a pure functional language, has immutable 'variables'. In such languages, the distinction between name/value and name/variable mappings is irrelevant. Thus the wikipedia entry's choice of using ML as an example is unfortunate.

    I definitely recommend learnign Lisp. I studied the pre-standardization document (Guy Steele's "Common Lisp" ) in detail early in my career (just prior to standardization), and it helped me immensely in understanding many issues of programming language design.

    Nowadays I doubt I'd have the fortitude to read through a language specification like this, though. Too busy reading blogs. :)

  • Anonymous
    November 20, 2005
    The comment has been removed

  • Anonymous
    July 08, 2006
    I believe that the point Ian Griffiths made on BradA's blog about the definition of closure being too implementation specific is at the center of the confusion here.  

    In Lisp, the compiler actually creates "a closure", a container if you will, for the lexical context of the function.  In .NET, according to the discussion on BradA's blog and inferred from Eric Gunnerson's comments on Channel9, the variables referenced by the anonymous methods are moved from the stack to the heap so that the "closed over" variables can be referenced in a shared manner independent of the lexical scope where they were declared.

    In short, the difference between "a closure" and an "anonymous method" is semantics.  They both form a logical lexical closure.  They only vary in their implementations.

  • Anonymous
    January 30, 2007
    PingBack from http://blog.darioquintana.com.ar/2006/10/07/predicados-y-especificaciones/

  • Anonymous
    May 21, 2007
    This works....using System;using System.Collections.Generic;using System.Text;namespace Assignment14{   class AnonymousExample {       public delegate string proc1();       public static proc1 delay(proc1 p)       {           string value = null;           return delegate()           {               if (value == null)               {                   value = p.Invoke();                   return value;               }               else               {                   return value;               }           };       }       public string foo()       {           Console.WriteLine("Thinking about foo");           return "fu";       }       public string bar()       {           Console.WriteLine("thinking about bar");           return "British American Racing";       }       public static void Main26()       {           AnonymousExample ae = new AnonymousExample();           proc1 p, q, r, s;           r = ae.foo;           s = ae.bar;           p = delay(r);           q = delay(s);           Console.WriteLine(p.Invoke());           Console.WriteLine(q.Invoke());           Console.WriteLine(p.Invoke());           Console.WriteLine(q.Invoke());       }   }}

  • Anonymous
    August 13, 2007
    PingBack from http://kohari.org/2007/08/13/more-on-thread-safe-invocation/

  • Anonymous
    November 21, 2007
    The comment has been removed

  • Anonymous
    June 02, 2008
    PingBack from http://gen5.info/q/2008/06/02/keeping-track-of-state-in-asynchronous-callbacks/

  • Anonymous
    June 24, 2008
    Open this post and read what I think about that:,

  • Anonymous
    November 17, 2008
    PingBack from http://coffee3.org/2008/11/17/anonymous-delegates-in-csharp/

  • Anonymous
    January 29, 2009
    PingBack from http://technojazda.wikidot.com/csharpclosures

  • Anonymous
    April 06, 2009
    On the advice of Jay Wren , I decided to try our ReSharper 4.1 .&#160; I had previously installed DevExpress

  • Anonymous
    April 06, 2009
    On the advice of Jay Wren , I decided to try our ReSharper 4.1 .&#160; I had previously installed DevExpress&#39;

  • Anonymous
    February 26, 2010
    After reading the discussion I decided never use anonymous delegates. They can be a source of very hard to find bugs.

  • Anonymous
    March 05, 2010
    Here it is without anonymouse methods! Much easier!! and we can easily manipulate it to create 1 2 3 4 5 6 7 8 9 or 10 10 10 10 10 10 ..without guess work. using System; using System.Text; namespace AnonymousMethod {    delegate void Func();    class Iholder    {          private int i;        public Iholder (int j) {i=j;}        public void writei()         {    Console.Write("{0} ", i);}        public void setvalue(int j) {i=j;}    }    class Program    {        static Func[] funcArr = new Func[10];        static void fillFunc(int count)        {            for (int i = 0; i < count; i++)            {                Iholder i_=new Iholder(i);                funcArr[i] = i_.writei;            }        }        static void Main(string[] args)        { 24           fillFunc(funcArr.Length);            for (int i=0;i<funcArr.Length; i++)            {              funcArri;            }        }    } }

  • Anonymous
    March 13, 2010
    Guess what happens when you move: int j = i; even deeper right into the Annoyingmouse :) method ?? Will it return 1 2 3 4 .. or 10 10 10 10  ... Well if you guessed 1 2 3 4 .. like I did you are wrong!! I suggest you stay away from them and write the code out into a proper method! using System; namespace AnnoyingMouseMethod { 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()  { int j = i;   Console.Write("{0} ", j);  }; } } static void Main(string[] args) { fillFunc(funcArr.Length); for (int i = 0; i < funcArr.Length; i++)  {   funcArri;  } } } }

  • Anonymous
    January 23, 2014
    and the fact that you work for microsoft!!!!!

  • Anonymous
    September 04, 2015
    int i is local to the for loop block so it is always reinitialize; the scope of for loop blocks changed about 2000-2002 (can't remember).  if you were to use a while loop and declare the int i outside the while loop then you would get the expected behavior.  In the Ruby example, the for loop scoping is similar to the old school C for loop style scoping.