Alex Rivera | Logout

foreach vs someList.ForEach(){}

Asked 2008-10-22T14:19:06.760
215

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...

Edit
Report

2 Answers

21

For fun, I popped List into reflector and this is the resulting C#:

public void ForEach(Action<T> action)
{
    if (action == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        action(this._items[i]);
    }
}

Similarly, the MoveNext in Enumerator which is what is used by foreach is this:

public bool MoveNext()
{
    if (this.version != this.list._version)
    {
        ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
    }
    if (this.index < this.list._size)
    {
        this.current = this.list._items[this.index];
        this.index++;
        return true;
    }
    this.index = this.list._size + 1;
    this.current = default(T);
    return false;
}

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.

answered 2008-10-22T14:53:48.080
2

Behind the scenes, the anonymous delegate gets turned into an actual method so you could have some overhead with the second choice if the compiler didn't choose to inline the function. Additionally, any local variables referenced by the body of the anonymous delegate example would change in nature because of compiler tricks to hide the fact that it gets compiled to a new method. More info here on how C# does this magic:

http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx

answered 2008-10-22T14:26:44.857

Your Answer