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 removedAnonymous
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 removedAnonymous
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/csharpclosuresAnonymous
April 06, 2009
On the advice of Jay Wren , I decided to try our ReSharper 4.1 .  I had previously installed DevExpressAnonymous
April 06, 2009
On the advice of Jay Wren , I decided to try our ReSharper 4.1 .  I had previously installed DevExpress'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.