Anonymous Delegates and Outer Variables Capturing
The following code doesn’t do what I want it to do:
List<Action<string>> actions = new List<Action<string>>();
int[] arr = { 1, 2, 3, 4, 5 };
foreach (int i in arr)
{
actions.Add(delegate{ Console.WriteLine(i); });
}
foreach (Action<string> action in actions)
{
action(null);
}
The issue turns out to be local variable lexical scoping. To
simplify the spec, if an anonymous delegate needs to capture an outer variable
(be it a method parameter, local variable, etc), it will get created in the
lexical scope of the variable. If
there are several of those, in the deepest lexical scope, of course.
The issue above is what the lexical scope of the “int i" variable
is. Considering that you can’t use the variable outside the loop, and
that you can define another variable afterward with the same name, I assumed
that the lexical scope of the variable is the loop. It looks like I was
mistaken. The code above would output five lines of 5.
The variable scope is the method scope. The workaround for
this is to add a new variable inside
the loop, and assign the variable to it.
This is covered in the C#
Spec in section 21.5.2 and it is damn
annoying.
Comments
Comment preview