There are apparently many ways to iterate over a collection. Curious if there are any differences, or why you'd use one way over the other.
First type:
List<string> someList = <some way to init>
foreach(string s in someList) {
<process the string>
}
Other Way:
List<string> someList = <some way to init>
someList.ForEach(delegate(string s) {
<process the string>
});
I suppose off the top of my head, that instead of the anonymous delegate I use above, you'd have a reusable delegate you could specify...
The ForEach function is member of the generic class List.
I have created the following extension to reproduce the internal code:
So a the end we are using a normal foreach (or a loop for if you want).
On the other hand, using a delegate function is just another way to define a function, this code:
is equivalent to:
or using labda expressions:
The entire ForEach scope (delegate function) is treated as a single line of code (calling the function), and you cannot set breakpoints or step into the code. If an unhandled exception occurs the entire block is marked.
One thing to be wary of is how to exit from the Generic .ForEach method - see this discussion. Although the link seems to say that this way is the fastest. Not sure why - you'd think they would be equivalent once compiled...
We had some code here (in VS2005 and C#2.0) where the previous engineers went out of their way to use
list.ForEach( delegate(item) { foo;});
instead offoreach(item in list) {foo; };
for all the code that they wrote. e.g. a block of code for reading rows from a dataReader.I still don't know exactly why they did this.
The drawbacks of
list.ForEach()
are:It is more verbose in C# 2.0. However, in C# 3 onwards, you can use the "
=>
" syntax to make some nicely terse expressions.It is less familiar. People who have to maintain this code will wonder why you did it that way. It took me awhile to decide that there wasn't any reason, except maybe to make the writer seem clever (the quality of the rest of the code undermined that). It was also less readable, with the "
})
" at the end of the delegate code block.See also Bill Wagner's book "Effective C#: 50 Specific Ways to Improve Your C#" where he talks about why foreach is preferred to other loops like for or while loops - the main point is that you are letting the compiler decide the best way to construct the loop. If a future version of the compiler manages to use a faster technique, then you will get this for free by using foreach and rebuilding, rather than changing your code.
a
foreach(item in list)
construct allows you to usebreak
orcontinue
if you need to exit the iteration or the loop. But you cannot alter the list inside a foreach loop.I'm surprised to see that
list.ForEach
is slightly faster. But that's probably not a valid reason to use it throughout , that would be premature optimisation. If your application uses a database or web service that, not loop control, is almost always going to be be where the time goes. And have you benchmarked it against afor
loop too? Thelist.ForEach
could be faster due to using that internally and afor
loop without the wrapper would be even faster.I disagree that the
list.ForEach(delegate)
version is "more functional" in any significant way. It does pass a function to a function, but there's no big difference in the outcome or program organisation.I don't think that
foreach(item in list)
"says exactly how you want it done" - afor(int 1 = 0; i < count; i++)
loop does that, aforeach
loop leaves the choice of control up to the compiler.My feeling is, on a new project, to use
foreach(item in list)
for most loops in order to adhere to the common usage and for readability, and uselist.Foreach()
only for short blocks, when you can do something more elegantly or compactly with the C# 3 "=>
" operator. In cases like that, there may already be a LINQ extension method that is more specific thanForEach()
. See ifWhere()
,Select()
,Any()
,All()
,Max()
or one of the many other LINQ methods doesn't already do what you want from the loop.List.ForEach() is considered to be more functional.
List.ForEach()
says what you want done.foreach(item in list)
also says exactly how you want it done. This leavesList.ForEach
free to change the implementation of the how part in the future. For example, a hypothetical future version of .Net might always runList.ForEach
in parallel, under the assumption that at this point everyone has a number of cpu cores that are generally sitting idle.On the other hand,
foreach (item in list)
gives you a little more control over the loop. For example, you know that the items will be iterated in some kind of sequential order, and you could easily break in the middle if an item meets some condition.For fun, I popped List into reflector and this is the resulting C#:
Similarly, the MoveNext in Enumerator which is what is used by foreach is this:
The List.ForEach is much more trimmed down than MoveNext - far less processing - will more likely JIT into something efficient..
In addition, foreach() will allocate a new Enumerator no matter what. The GC is your friend, but if you're doing the same foreach repeatedly, this will make more throwaway objects, as opposed to reusing the same delegate - BUT - this is really a fringe case. In typical usage you will see little or no difference.