EightyOne Unite
EightyOne Unite

Reputation: 11795

.Net - When is List<T>.ForEach prefered over a standard foreach loop?

The generic list class has a .ForEach(Action<T> action) method. Now i've done some simple timings of how they both perform and it seems that the generic ForEach is the poorer performer. The (Snippet Compiler Friendly) code is below -

public static class timer{
    public static long foreachloop = 0;
    public static long Gforeachloop = 0;}

public class something{
    public List<string> myStrings = new List<string>();

    public something()
    {
        for(int i = 1; i<=5000000;i++)
        {
            myStrings.Add(i.ToString());
        }
    }}

public class cls1{
    private static List<string> Strings = new List<string>();
    private static List<string> OtherStrings = new List<string>();

    public static void RunSnippet()
    {
        something s = new something();

        Stopwatch watch = new Stopwatch();
        watch.Start();
        foreach(string x in s.myStrings)
        {
            Strings.Add(x);
        }
        watch.Stop();
        timer.foreachloop = watch.ElapsedMilliseconds;

        watch.Reset();
        watch.Start();

        s.myStrings.ForEach(delegate(string n){OtherStrings.Add(n);});

        s.myStrings.Clear();

        watch.Stop();
        timer.Gforeachloop = watch.ElapsedMilliseconds;

        WL("FOREACH-"+timer.foreachloop + ",Count = " + Strings.Count);
        WL("GFOREACH-"+timer.Gforeachloop + ",Count = " + OtherStrings.Count);
    }

    #region Helper methods

    public static void Main()
    {
        try
        {
            RunSnippet();
        }
        catch (Exception e)
        {
            string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
            Console.WriteLine(error);
        }
        finally
        {
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }
    }

    private static void WL(object text, params object[] args)
    {
        Console.WriteLine(text.ToString(), args);   
    }

    private static void RL()
    {
        Console.ReadLine(); 
    }

    private static void Break() 
    {
        System.Diagnostics.Debugger.Break();
    }

    #endregion
}

FOREACH comes out at 177ms and GFOREACH at 707ms.

Now I'm guessing there's a good reason for using it but i just can't think of one. Clearly performance isn't the reason so the question is when would it be the best option?

Thanks in advance.

Upvotes: 4

Views: 1037

Answers (2)

Daniel Earwicker
Daniel Earwicker

Reputation: 116654

This blog post from Eric Lippert gives the background:

http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

He's talking about the common suggestion of an extension method to do the same thing for IEnumerable<T>, but the philosophical objection applies to List<T>.ForEach as well.

This suggests that maybe that method was never such a good idea, although it looks "cool". It's clearer to just use foreach.

I've suggested that such methods can be thought of as a fix for the classic closure-over-loop-variable bug.

But in practice I've just got better at spotting such bugs.

Upvotes: 7

Mehrdad Afshari
Mehrdad Afshari

Reputation: 421978

When it looks neater.

Not a joke at all. Really, I mean it. Go with the more readable style in your case. For instance, if you just want to call a method on each item like:

list.ForEach(Console.WriteLine);

this style suits better. However, if you are having a hundred lines as the body of the loop, or you have nested loops and control flow constructs, the old style looks better.

Upvotes: 6

Related Questions