When using lambda expressions or anonymous methods in C#, we have to be wary of the access to modified closure pitfall. For example:
foreach (var s
In C# 5.0, this problem is fixed and you can close over loop variables and get the results you expect.
The language specification says:
8.8.4 The foreach statement
(...)
A foreach statement of the form
foreach (V v in x) embedded-statement
is then expanded to:
{ E e = ((C)(x)).GetEnumerator(); try { while (e.MoveNext()) { V v = (V)(T)e.Current; embedded-statement } } finally { … // Dispose e } }
(...)
The placement of
v
inside the while loop is important for how it is captured by any anonymous function occurring in the embedded-statement. For example:int[] values = { 7, 9, 13 }; Action f = null; foreach (var value in values) { if (f == null) f = () => Console.WriteLine("First value: " + value); } f();
If
v
was declared outside of the while loop, it would be shared among all iterations, and its value after the for loop would be the final value,13
, which is what the invocation off
would print. Instead, because each iteration has its own variablev
, the one captured byf
in the first iteration will continue to hold the value7
, which is what will be printed. (Note: earlier versions of C# declaredv
outside of the while loop.)