Home of the AlmostImplementedException

Unexpected behavior of foreach

When a program produces wrong results sometimes(!) your code is not the problem, but the compiled result. Thats nothing new, but most developers are not aware of it.
It doesn’t necessarily mean, there is a bug in the compiler. Maybe you (and the rest of the world) just expected another behavior.

Today I want to show you a little problem with foreach, which is “fixed” with C# 5 (.Net 4.5). It has no practical impact in most cases, so you shouldn’t jump to the conclusion that foreach is “bad”.

When you use a for-loop you decide in which context a variable is used. You can use a variable in the context of the loop (which means it’s gone after the loop is finished) or a global one.
If you iterate over a list and the object is used only inside the loop, you’ll use a loop-context-variable (=> CleanCode: Use the right context for your variable).

And here is a little example:

As you can see the variable obj is declared in the context of the loop.

When you use foreach, you can’t decide the context of your variable, but would expect something similar to the example above as result. And since C# 5, thats true.
But before that, in fact it’s not. You’ll get a variable outside the loop-context.

As mentioned before it doesn’t matter in most cases. But here is an example where it does. And also it’s a good example of unclean code.

In order to demonstrate the problem, we have to find a way to postpone the use of the loop-variable. A good way to do that are lambda-expressions. They don’t use the actual value of a variable, they use the variable instead. And that is one thing you should remember about lambda-expressions (e.g. as tricky interview question).
Instead of the expected result of “1 2 3 4″, you’ll get ” 4 4 4 4″ (use .Net 4 and try it yourself).

But what is the conclusion? Not to use foreach? NO!

The first conclusion is: Be aware of such behaviors!
The second, and in my opinion more important one is: Write clean code!

Which means:
– do it as simple as possible
– use constructs most (good) developers would understand
– use the right pattern for the problem

Especially the last point is the crux of clean code. What is the right pattern?
Ask 2 developers this question and you will get 3 different answers 🙂

But more on this matter next time…

For more details why foreach worked that way:

Share :

Leave a Reply