News for hackers. Stuff that matters.
Re:C# Language Specification 5.0 by skwirl on Monday June 24, 2013 @11:15PM (#5937302)
An interesting change in C# 5.0 involves the handling of foreach iteration variables when used in closure scope. This is technically a breaking change, although it is really hard to think of a case where the old behavior was legitimately desired.

Consider (stolen from the spec doc):

  int[] values = { 7, 9, 13 };
  Action f = null;
  foreach (var value in values)
  {
      if (f == null) f = () => Console.WriteLine("First value: " + value);
  }
  f();
In previous versions of C#, there is a single value variable is in the scope of the entire loop, so the above code would actually print out the last value in the list because that was the value of value (sorry) when the loop finished. In C# 5.0, a value variable is actually in the scope of each individual iteration (so within the braces). So now if you use your iteration variable in a closure scope it won't change on you when the loop iterates and the above code actually prints out the first value.

The same cannot be said for a for loop. It still functions as it always has.

Re:C# Language Specification 5.0 by danbruc on Monday June 24, 2013 @11:25PM (#5937327)
Here is Eric Lippert discussing the pros and cons of making the change.

http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closi...

Re:C# Language Specification 5.0 by gnaritas on Monday June 24, 2013 @11:30PM (#5937343)
Should have been that way from the beginning; having the loop variable have function scope was absurd to begin with and forced developers to copy the loop var to a local before using it in a lambda.
Re:C# Language Specification 5.0 by skwirl on Monday June 24, 2013 @11:45PM (#5937392)
Yeah, they could have made the change in C# 3.0. I just don't think anyone really felt the pain until the Task Parallel Library came along in .NET 4. Since the TPL API is lambda heavy people really started using lambdas for asynchronous tasks, which leads (or used to lead, anyway) to pain and misery when using a loop iteration variable.

It could always be worse, though. Look at JavaScript. Simply copying the loop variable in the body of the loop doesn't work because all variables are scoped at the function level. So your "local" loop variable is actually a single instance for the entire function and you have the same exact problem. Instead, you have to actually create another function and immediately execute it with the loop iteration variable as an argument, and then use the parameter within the function to do whatever you wanted to do. Not cool.

Re:C# Language Specification 5.0 by gnaritas on Monday June 24, 2013 @11:53PM (#5937415)
Agreed.
Re:C# Language Specification 5.0 by keyle on Tuesday June 25, 2013 @12:07AM (#5937455)
Good nitpicking. But as you indicated, the change of behaviour should only affect people with a very dubious/interesting approach.
Re:C# Language Specification 5.0 by seanmcdirmid on Tuesday June 25, 2013 @12:38AM (#5937558)
No, this bug was encountered often by myself and many of my colleagues. Because I was so familiar with the problem, I could guess that this was a problem in their code after looking at it for a few seconds.

It really was a horrible wart that needed to be fixed.

Now if they would only fix the misleading lying dishonest "downcast on type bound" compiler error messages, then C# would lack warts all together.

Re:C# Language Specification 5.0 by pixie_ on Tuesday June 25, 2013 @11:45AM (#5940276)
The OP wasn't saying, 'this bug isn't a big deal.' He's saying, 'the bug fix shouldn't break existing programs.' Because people, like you, designed around this. Few people, if any, designed their apps to rely on the value in the loop not changing - that's why this 'breaking fix' should break almost no programs.
Re:C# Language Specification 5.0 by seanmcdirmid on Tuesday June 25, 2013 @09:13PM (#5943505)
Yes, you are right, my reading comprehension of OP's comment sucks.
Re:C# Language Specification 5.0 by sk5t on Tuesday June 25, 2013 @01:04AM (#5937644)
Same here, it bit me quite a few times and was highly irritating each time. Very annoying to choose between copying the loop variable, or passing it off to some other method to gin up an action/func safely.