C# 2.0 closures - bug or feature?  
Author Message
Andrew Skalkin





PostPosted: Visual C# Language, C# 2.0 closures - bug or feature? Top

Would anyone care to explain me what is happening there To me, both i and ii seem to be local variables within the same scope, so why the compiler treats them differently

using System;
using System.Collections.Generic;

internal delegate void VoidDelegate();

internal class Program
{
private static void Main()
{
List<int> a = new List<int>();
for (int i = 0; i < 10; i++)
{
a.Add(i);
}

List<VoidDelegate> handlers = new List<VoidDelegate>();
foreach (int i in a)
{
handlers.Add(delegate { Console.Write(i); });
//If we comment out line above and uncomment two lines below, we'll get the expected "0123456789" result.
//int ii = i;
//handlers.Add(delegate { Console.Write(ii); });

}

foreach (VoidDelegate action in handlers)
{
action();
}
}
}

P.S. How to insert C# code snippets on this forum


Visual C#3  
 
 
xRuntime





PostPosted: Visual C# Language, C# 2.0 closures - bug or feature? Top

What result do you get when the code is like that


 
 
Andrew Skalkin





PostPosted: Visual C# Language, C# 2.0 closures - bug or feature? Top

"9999999999" in the original version, "0123456789" if you uncomment the code

 
 
Andrew Skalkin





PostPosted: Visual C# Language, C# 2.0 closures - bug or feature? Top

I got it - it is very well described in #21.5.2: Instantiation of local variables -

Ordinarily, there is no way to observe exactly how often a local variable is instantiated—because the lifetimes of the instantiations are disjoint, it is possible for each instantation to simply use the same storage location. However, when an anonymous method captures a local variable, the effects of instantiation become apparent. The example

using System;
delegate void D();
class Test
{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
resultIdea = delegate { Console.WriteLine(x); };
}
return result;
}
static void Main() {
foreach (D d in F()) d();
}
}
produces the output:
1
3
5