.Net - 什么时候是List <t> .ForEach优于标准的foreach循环?</t>

时间:2009-07-23 16:35:27

标签: c# performance generics generic-list

通用列表类有.ForEach(Action<T> action)方法。现在我已经完成了一些简单时间表示它们的表现,而且通用的ForEach似乎表现得更差。 (Snippet Compiler Friendly)代码如下 -

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出现在177ms,GFOREACH出现在707ms。

现在我猜这是使用它的一个很好的理由,但我想不出一个。显然,性能不是原因所以问题是它什么时候才是最佳选择?

提前致谢。

2 个答案:

答案 0 :(得分:7)

Eric Lippert撰写的这篇博文提供了背景资料:

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

他正在谈论为IEnumerable<T>做同样事情的扩展方法的共同建议,但哲学上的反对也适用于List<T>.ForEach

这表明也许这种方法从来都不是一个好主意,虽然它看起来很“酷”。使用foreach更清楚。

我建议将此类方法视为a fix for the classic closure-over-loop-variable bug

但在实践中,我只是更好地发现了这些错误。

答案 1 :(得分:6)

看起来更整洁。

根本不是开玩笑。真的,我的意思是。在您的情况下,使用更易读的样式。例如,如果您只想在每个项目上调用方法,例如:

list.ForEach(Console.WriteLine);

这种风格更适合。但是,如果你有一百行作为循环体,或者你有嵌套循环和控制流结构,旧样式看起来更好。