C# .Net-何时为列表<;T>;。ForEach优先于标准ForEach循环?

C# .Net-何时为列表<;T>;。ForEach优先于标准ForEach循环?,c#,performance,generics,generic-list,C#,Performance,Generics,Generic List,泛型列表类有一个.ForEach(Action-Action)方法。现在我做了一些简单的计时,看样子通用ForEach的性能较差。(代码段编译器友好)代码如下- public static class timer{ public static long foreachloop = 0; public static long Gforeachloop = 0;} public class something{ public List<string> myStr

泛型列表类有一个
.ForEach(Action-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
}
公共静态类计时器{
公共静态长foreachloop=0;
公共静态长Gforeachloop=0;}
公开课{
public List myStrings=new List();
公开某事
{
对于(inti=1;i,当它看起来更整洁时

一点也不开玩笑。真的,我是认真的。在你的案例中,使用更具可读性的样式。例如,如果你只想对每个项目调用一个方法,如:

list.ForEach(Console.WriteLine);

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

Eric Lippert的这篇博文提供了以下背景:

他说的是一种常见的扩展方法,可以对
IEnumerable
做同样的事情,但哲学上的反对意见也适用于
List.ForEach

这表明,尽管该方法看起来“很酷”,但它可能从来都不是一个好主意。只使用
foreach
更为清晰

我建议,这种方法可以被认为是一种新的方法


但在实践中,我更擅长发现这样的bug。

相关/重复?他主要在
IEnumerable
上谈论
.ForEach
(你在那里链接和编写东西),而不是在
List
上,您希望在一行中对列表中的每个对象执行一个方法。但是,对于
IEnumerable
上的
ForEach
是可组合的,没有广泛的共识。显然,一致的实现是模仿
List.ForEach
并返回void,就像Eric在他的博客po中所做的那样同样的哲学上的反对意见也适用于这两者。关于循环变量闭包问题,我只希望他们能让匿名委托和lambdas“聪明”关于循环变量,默认情况下捕获循环变量的副本。在极少数情况下,编码人员打算从lambda内部修改循环变量,他们可以对其进行编码。其他99%的情况下,我们的生活会更轻松。我想,其中一件事现在很难解决。可能吧。你的推理是正确的然而,事实上,他们决定使用
List.ForEach
Array.ForEach
(两者都出现在.NET 2.0中),并且他们没有提供
可枚举的.ForEach
扩展方法(在3.5中)这让我觉得有不同的哲学原因。基本上,我猜是
List。ForEach
设计用于已经存在的集合,而不是查询的结果。顺便说一句,我认为性能确实是他们为frameworkI中的数组和列表提供
ForEach
的原因之一nk Eric博客上那篇文章中的这句话证明了这一点:“我不喜欢做唯一一个只对副作用有用的序列操作符。”显然,在2.0中,当添加了
Array.ForEach
List.ForEach
时,它们并不打算用作序列运算符;因此博客条目并不真正适用于它们。只是在我看来很奇怪。我会发现标准ForEach在视觉上更容易使用。AnthonyWJones:我认为这主要是因为我们习惯于使用tive编程。对于使用函数式语言的程序员来说,这种风格显然更为自然。@Mehrdad-不完全如此。看看Haskell。当编写带有副作用的命令式代码时(这就是全部内容),它们使用一种特殊的单子语法,模仿命令式语言的风格。哦,我还以为你指的是真正的函数式语言呢!:P@Mehrdad:是的,我习惯命令式编程,C#主要是命令式编程。最近,它开始支持一种不断增长的函数式编程风格。问题就在于,我想要我的fam伊利亚的东西,必须继续保持它一直以来的样子,而功能性的东西,看起来功能性的。这有助于我区分这些非常不同的思维方式。