C# – Lambda expressions and access to modified closure
When I use Lambda expressions, I find out a strange and unexpected behavior. Let’s consider the following example
static ICollection<Func<string>> CreateExample1()
{
ICollection<Func<string>> lstFunctions = new LinkedList<Func<string>>();
for (int nIndex = 0; nIndex < cnst_nCount; nIndex++)
{
lstFunctions.Add(() => nIndex.ToString());
}
return lstFunctions;
}
static void Print(ICollection<Func<string>> lstFunctions)
{
Console.WriteLine(string.Join(", ", lstFunctions.Select(f => f()).ToArray()));
}
What are we waiting for when calling Print(CreateExample1())? An output with “0, 1, 2, 3″? The answer is no. When we compile and run the code above we will have a black screen with array of “4, 4, 4, 4″. Why doesn’t it run correctly? Let’s go back to review how the Lambda expression work.
A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
All lambda expressions use the lambda operator =>, which is read as “goes to”. The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block.
The important feature of lambda expression that we must know is that it is evaluated during run-time. That means, in the example above, the lambda expression will be “compiled and executed” only when the for-loop starts to run. Therefore when the expression is being evaluated, the value of nIndex variable was changed and in our case the nIndex reaches it up-bound already when the evaluation of expression is going on.
To solve this problem, what we should do is pushing our variable nIndex into stack and when the expression is evaluated, it will pop the value from stack for its calculation.
To push value into stack, we can use a temporary variable to store current value of iteration variable.
static ICollection<Func<string>> CorrectExample()
{
ICollection<Func<string>> lstFunctions = new LinkedList<Func<string>>();
for (int nIndex = 0; nIndex < cnst_nCount; nIndex++)
{
int j = nIndex;
lstFunctions.Add(() => j.ToString());
}
return lstFunctions;
}
So in the end of this blog, remember this hint “Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it the value of the iteration variable.”

Not only Lambda has the problem, almost language support anonymous method has the problem, below is an example in javascript:
function init() {
window[\funcs\] = {};
for(var i = 1; i < 5; i++) {
window.funcs["func_" + i] = function() {
alert(i);
}
}
}
function test() {
for(var name in window.funcs) {
window.funcs[name]();
}
}
init();
test();
Thanks. I just ran into this and came to this conclusion and you corroborated my finding. I didn’t know about the variable declaration within the loop being used to solve the problem. Good to have in my toolbox.
Leave your response!
Computer security »
Hacking – How to hack WPA/WPA2 Password with BackTrack through cracking WPS?
Last week I’ve read small news on c’t magazine saying that the default password of EasyBox router used for Vodafone, Telecom, Arcor in Germany … was hacked by Sebastian Petters. That means if someone is using default settings of EasyBox, you can get his WLAN password easily and then access his network. This default password was generated by a algorithm and this algorithm was patented. Therefore like other patents, the complete description of algorithm was …
Programming »
How to install Google Maps v2 in Android Emulator and use it in Intellij Idea?
Integrating Google Maps (or any map service) is always a nice feature for our applications, but it seems to be “complicated” for integrating Google Maps because Google Maps is not officially supported in emulator because lacking of Google Play Service. That forces us to use a real device during developing app. For me, not nice. So in this post, I would like to show step by step how I configure my emulator so that a …
Tutorial »
How to install Google Maps v2 in Android Emulator and use it in Intellij Idea?
Integrating Google Maps (or any map service) is always a nice feature for our applications, but it seems to be “complicated” for integrating Google Maps because Google Maps is not officially supported in emulator because lacking of Google Play Service. That forces us to use a real device during developing app. For me, not nice. So in this post, I would like to show step by step how I configure my emulator so that a …
Donation
Archives
Blogroll
Tag Cloud
.net reactor 64 bit 2012 android asp.net asp.net web api auto backtrack c# codeveil 3.x database domain emulator firefox game hack hacking linq munich mvvm online notes password php rest reverse engineering security sharepoint silverlight ssh theme tlbb tool trip twitter visual studio wallpaper wcf web service windows windows 7 windows phone word wpf xml yahoo messenger