views:

649

answers:

2

I was just writing some quick code and noticed this complier error

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.

I know what it means and I can easily fix it, not a big deal.
But I was wondering why it is a bad idea to use a iteration variable in a lambda? What problems can I cause later on?

EDIT! Sorry I'm using VB.net

+2  A: 

Assuming you mean C# here.

It's because of the way the compiler implements closures. Using an iteration variable can cause a problem with accessing a modified closure (note that I said 'can' not 'will' cause a problem because sometimes it doesn't happen depending on what else is in the method, and sometimes you actually want to access the modified closure).

More info:

http://blogs.msdn.com/abhinaba/archive/2005/10/18/482180.aspx

Even more info:

http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx

http://blogs.msdn.com/oldnewthing/archive/2006/08/03/687529.aspx

http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx

Greg Beech
It's not "one closure per method" - it's more complicated than that.
Jon Skeet
Yeah I realise that read badly - I was trying to paraphrase the situation quickly (Raymond explains in more depth). Removed the offending phrase so people can look at the more info links.
Greg Beech
+11  A: 

Consider this code:

List<Action> actions = new List<Action>();

for (int i=0; i < 10; i++)
{
    actions.Add(() => Console.WriteLine(i));
}

foreach (Action action in actions)
{
    action();
}

What would you expect this to print? The obvious answer is 0...9 - but actually it prints 10, ten times. It's because there's just one variable which is captured by all the delegates. It's this kind of behaviour which is unexpected.

EDIT: I've just seen that you're talking about VB.NET rather than C#. I believe VB.NET has even more complicated rules, due to the way variables maintain their values across iterations. This post by Paul Vick gives some information about the kind of difficulties involved - although it's back from 2006, so the actual behaviour may have changed since then.

Jon Skeet