C# lambda, local variable value not taken when you think?

This is a modified closure

See: similar questions like Access to Modified Closure

To work around the issue you have to store a copy of the variable inside the scope of the for loop:

   foreach(AClass i in AClassCollection) 
   { 
      AClass anotherI= i;
      listOfLambdaFunctions.AddLast(  () =>  {  PrintLine(anotherI.name); }  ); 
   } 

does the lambda function somehow store a 'reference' to the variable or something?

Close. The lambda function captures the variable itself. There is no need to store a reference to a variable, and in fact, in .NET it is impossible to permanently store a reference to a variable. You just capture the entire variable. You never capture the value of the variable.

Remember, a variable is a storage location. The name "i" refers to a particular storage location, and in your case, it always refers to the same storage location.

Is there anyway around this problem?

Yes. Create a new variable every time through the loop. The closure then captures a different variable every time.

This is one of the most frequently reported problems with C#. We're considering changing the semantics of the loop variable declaration so that a new variable is created every time through the loop.

For more details on this issue see my articles on the subject:

http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/


what is going on? does the lambda function somehow store a 'reference' to the variable or something?

Yes exactly that; c# captured variables are to the variable, not the value of the variable. You can usually get around this by introducing a temp variable and binding to that:

string astr = "a string";
var tmp = astr;
AFunc fnc = () => { System.Diagnostics.Debug.WriteLine(tmp); };

especially in foreach where this is notorious.

Tags:

C#

Lambda