Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top