C#: The Dangers of Foreach
July 8, 2008
Although very handy, C#'s
foreach statement is actually quite dangerous.
In fact, I may swear off its use entirely. Why? Two reasons: (1) performance, and
Iterating through a collection using
foreach is slower than with
for. I can't remember where I first learned that, perhaps in
Patterns & Practices:
Improving .Net Application Performance. Maybe it was from personal experience.
How much slower? Well, I suppose that depends on your particular circumstances.
Here are a few interesting references:
- FOREACH Vs. FOR
(C#): shows the extra IL code created for a
- To foreach or not to foreach that is the question: claims it isn't so clear-cut, at least for regular arrays. Not absolutely conclusive.
I was looking at the C# Reference entry for foreach today and noticed this for the first time (italics added by me):
The foreach statement is used to iterate through the collection to get the desired information, but should not be used to change the contents of the collection to avoid
unpredictable side effects.
What's that all about? Let's take this as an example:
foreach(MyClass myObj in List<MyClass>)
Looking deeper into the
Specification... the iteration variable is supposed to be read-only, though
apparently that doesn't stop you from updating a property of an object. Thus for
instance it would be illegal to assign a new value to
myObj, but not
to assign a new value to
And that's all I can find. Why are there unpredictable side effects? I don't know. But seems best to heed Microsoft's warning.
Some argue that you shouldn't code for performance from the beginning, and therefore
go ahead and use
foreach whenever you want so long as you don't update
the values. In my experience that's hogwash — most of the code I work on goes into
environments where performance is extremely important. Besides, writing a for statement
requires very little extra coding compared to a
Furthermore, if you have a lot going on inside your iteration block, it can be easy
to forget and accidentally update the iteration variable inside a
loop. Thus do I conclude: just avoid