Understanding C# Lambda Expression Capture in Loops and its Solution
C# lambda expressions within loops exhibit a common pitfall: they capture the same variable, leading to unexpected results. This occurs because the lambda expression doesn't capture the value of the variable at the time of its creation, but rather a reference to the variable itself. Consider this example:
List<Func<int>> actions = new List<Func<int>>(); int variable = 0; while (variable < 5) { actions.Add(() => variable * 2); ++variable; } foreach (var act in actions) { Console.WriteLine(act.Invoke()); }
Instead of the expected output (0, 2, 4, 6, 8), the code outputs five 8s. This is because all lambda expressions reference the final value of variable
(which is 10 after the loop completes), not its value at the time each lambda was created.
The Solution: Creating a Copy
To resolve this, create a copy of the loop variable within each iteration:
List<Func<int>> actions = new List<Func<int>>(); int variable = 0; while (variable < 5) { int copy = variable; // Create a copy actions.Add(() => copy * 2); ++variable; }
Now, each lambda expression captures a distinct copy
variable, resulting in the correct output.
C# 5 and Later: foreach and CATVs
In C# 5 and later versions, the foreach
loop's behavior has changed to address this issue. The compiler uses "closure allocation temporary variables" (CATVs) to automatically create a separate variable for each iteration, eliminating the need for manual copies. This simplification makes code cleaner and more readable. However, the while
loop example still requires the explicit copy.
The above is the detailed content of Why Do C# Lambda Expressions in Loops Capture the Same Variable, and How Can This Be Resolved?. For more information, please follow other related articles on the PHP Chinese website!