July 8, 2008
C#: The Dangers of Foreach
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
(2) predictability.
Performance
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
foreachloop - 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.
Predictability
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
C# Language
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 myObj.MyProperty.
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.
Conclusion
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 foreach statement.
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 foreach
loop. Thus do I conclude: just avoid foreach altogether.
Comments