3

通用列表类有一个.ForEach(Action<T> action)方法。现在我已经对它们的性能做了一些简单的计时,似乎通用的 ForEach 性能较差。(代码段编译器友好)代码如下 -

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

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

提前致谢。

4

2 回答 2

7

Eric Lippert 的这篇博文给出了背景:

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

他在谈论一个扩展方法的常见建议来做同样的事情IEnumerable<T>,但哲学上的反对也适用List<T>.ForEach

这表明也许这种方法从来都不是一个好主意,尽管它看起来“很酷”。使用foreach.

我建议可以将此类方法视为对经典闭包循环变量错误的修复

但在实践中,我在发现此类错误方面做得更好。

于 2009-07-23T16:42:35.450 回答
6

当它看起来更整洁时。

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

list.ForEach(Console.WriteLine);

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

于 2009-07-23T16:40:38.263 回答