2

I am trying to understand closures, already read some materials but.. then i tried this.

As far as i understand, a class is generated containing the specific anonymous method (in my case, the one writing to the console) and the int variable j. How does it store all the j values in only one class? Are there many instances of this kind of class generated behind the scenes?

class Program { public static List<Action> actions = new List<Action>(); static void Main(string[] args) { AddActions(10); actions[0](); actions[1](); Console.ReadLine(); } public static void AddActions(int count) { for (int i = 0; i < count; i++) { int j = i; actions.Add(delegate() { Console.Write("{0} ", j); }); } } } 

with result: 0 1

1

2 Answers 2

1

Here is your code decompiled into classes rather than lambdas.

private class Program { public static List<Action> actions; static Program() { Program.actions = new List<Action>(); } private static void Main(string[] args) { Program.AddActions(10); Program.actions[0](); Program.actions[1](); Console.ReadLine(); } public static void AddActions(int count) { for (int index = 0; index < count; ++index) { Program.\u003C\u003Ec__DisplayClass2_0 cDisplayClass20 = new Program.\u003C\u003Ec__DisplayClass2_0(); cDisplayClass20.j = index; Program.actions.Add(new Action((object)cDisplayClass20, __methodptr(\u003CAddActions\u003Eb__0))); } } private sealed class \u003C\u003Ec__DisplayClass2_0 { public int j; public \u003C\u003Ec__DisplayClass2_0() { base.\u002Ector(); } internal void \u003CAddActions\u003Eb__0() { Console.Write("{0} ", (object)this.j); } } } 

As you can see, for example iteration of the loop you get a new instance of new Program.\u003C\u003Ec__DisplayClass2_0();.

Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks, i become more and more aware of these things.
0

Yes, many instances are generated.

You need an the extra variable j in the scope of the loop body because the variable i has a scope of the method's body, and only a single closure object would be generated for it.

void Main() { AddActions(10); var closure1 = functions[0](); var closure2 = functions[1](); Console.WriteLine(object.ReferenceEquals(closure1, closure2)); // False } public static void AddActions(int count) { for (int i = 0; i < count; i++) { int j = i; functions.Add(delegate() { Console.WriteLine(j); Expression<Func<int>> exp = () => j; Console.WriteLine(exp.ToString()); var m = (MemberExpression)exp.Body; var c = (ConstantExpression)m.Expression; Console.WriteLine(c.Value.ToString()); return c.Value; }); } } public static List<Func<object>> functions = new List<Func<object>>(); 

Result

0 () => value(UserQuery+<>c__DisplayClass1_0).j UserQuery+<>c__DisplayClass1_0 1 () => value(UserQuery+<>c__DisplayClass1_0).j UserQuery+<>c__DisplayClass1_0 False 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.