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 generated

def 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 ' '

}

end

end

funcGen(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.call

end


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();

public void <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 = new Program.<>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 (27)

  1. Dan Muller says:

    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).

  2. Andreas says:

    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#.

  3. Wesner Moise says:

    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.

  4. Gabe says:

    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.

  5. 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.

  6. Dan Muller says:

    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?

  7. James Arendt says:

    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.

    }

    }

  8. Dan Muller says:

    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.

  9. 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…..

  10. Dan Muller says:

    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. 🙂

  11. Jon Harrop says:

    Dan Muller wrote:

    > 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.

    ML is not a pure functional language, it is an impure functional language (Haskell is an example of a pure functional language). So ML has both mutable and immutable variables.

    The OCaml equivalent of the original example programs is simply:

    let arr =

    Array.init 11 (fun i () -> Printf.printf "%d " i)

    Array.iter (fun f -> f ()) arr

    The first line creates an array of closures, each of which prints its own index in the array. The second line applies the final argument "()" to each of the closures, invoking them in turn and printing out the consecutive integers 0..10.

    I have no idea whether or not C# supports first-class lexical closures. I do know that other languages will have a tough time trying to beat the brevity and performance of ML though.

    Cheers,

    Jon.

    PS: Don’t try to learn anything about functional programming from Wikipedia – the articles are mostly awful and they seem to be getting worse…

  12. 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.

  13. Kiran A Digumarti says:

    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());

           }

       }

    }

  14. I had blogged earlier about Gardens Point Ruby.NET . After I read Don Box writing about it, I decided

  15. Plmnywix says:

    Open this post and read what I think about that:,

  16. On the advice of Jay Wren , I decided to try our ReSharper 4.1 .&#160; I had previously installed DevExpress

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

  18. leve says:

    After reading the discussion I decided never use anonymous delegates. They can be a source of very hard to find bugs.

  19. Gregor says:

    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++)

               {

                 funcArr[i]();

               }

           }

       }

    }

  20. Gregor says:

    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++)

     {

      funcArr[i]();

     }

    }

    }

    }

  21. Iqias says:

    and the fact that you work for microsoft!!!!!

  22. Mick Hill says:

    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.

Skip to main content