【问题标题】:C#: Any benefit of List<T>.ForEach(...) over plain foreach loop?C#:List<T>.ForEach(...) 比普通的 foreach 循环有什么好处?
【发布时间】:2010-12-27 19:52:16
【问题描述】:

我想知道为什么List&lt;T&gt;.ForEach(Action&lt;T&gt;) 存在。

这样做有什么好处/区别:

elements.ForEach(delegate(Element element){ element.DoSomething(); });

结束

foreach(Element element in elements) { element.DoSomething();}

?

【问题讨论】:

    标签: c# c#-3.0 foreach


    【解决方案1】:

    一个关键的区别是使用 .ForEach 方法,您可以修改基础集合。使用 foreach 语法,如果你这样做,你会得到一个异常。这是一个例子(不完全是最好看的,但它确实有效):

    static void Main(string[] args) {
        try {
            List<string> stuff = new List<string>();
            int newStuff = 0;
    
            for (int i = 0; i < 10; i++)
                stuff.Add(".");
    
            Console.WriteLine("Doing ForEach()");
    
            stuff.ForEach(delegate(string s) {
                Console.Write(s);
    
                if (++newStuff < 10)
                    stuff.Add("+"); // This will work fine and you will continue to loop though it.
            });
    
            Console.WriteLine();
            Console.WriteLine("Doing foreach() { }");
    
            newStuff = 0;
    
            foreach (string s in stuff) {
                Console.Write(s);
    
                if (++newStuff < 10)
                    stuff.Add("*"); // This will cause an exception.
            }
    
            Console.WriteLine();
        }
        catch {
            Console.WriteLine();
            Console.WriteLine("Error!");
        }
    
        Console.ReadLine();
    }
    

    【讨论】:

    • 这是因为在幕后,ForEach(Action&lt;T&gt;) 使用了一个 for 循环。在 Reflector 中,它看起来像这样:for (int i = 0; i &lt; this._size; i++) { action(this._items[i]); } 但是,如果您在循环时执行诸如在当前位置之前(例如位置 0)插入项目之类的操作,我认为您仍然有可能出现不稳定的结果。
    • (有趣的是,Reflector 还显示 Microsoft 的某个人草率地从 List&lt;T&gt; 方法之一使用名为“match”的参数剪切并粘贴了 null 检查。如果您将 null 作为 @ 987654326@,它会告诉你“match”参数为空,而不是正确的“action”参数。)
    • here 所述:自 .net 4.5 以来实现发生了变化,它们“都抛出”。
    【解决方案2】:

    它是very likely to be faster(您不应仅仅因为性能优势较小而选择其中一个,除非您正在处理计算量大的数字运算或图形应用程序,并且您需要充分利用处理器周期)并且您可以将委托直接传递给它,这在某些情况下可能很方便:

    list.ForEach(Console.WriteLine); // dumps the list to console.
    

    【讨论】:

    • 有没有其他人注意到这家伙正在执行 1000 万 次迭代?谈论节省 0.03 秒?在您在这些迭代中进行实际工作时,0.03 秒可能很重要吗?
    • Kyralessa:关键不在于它是否重要。两者之间存在技术差异,这对某些人来说可能很重要。这就是回答这个问题的全部意义所在。
    • @Gonzalo:ArrayList 没有 ForEach 方法。测试比较了List&lt;T&gt; 中的List&lt;T&gt;.ForEachforeach,对于数组也是如此。
    • 但这太荒谬了。谁在乎你是否在超过 1000 万次迭代中节省了 0.3 秒?您到底要在那些迭代速度如此之快以至于0.3 秒会产生影响的迭代中做什么?这是一个有趣的好奇心,但它根本没有现实价值。写出可读的代码。使用对阅读程序的人类 最有意义的循环结构。如果你真的需要节省 0.3 秒,你应该首先用 C 或 C++ 编写程序,而不是 C# 或 VB .NET。
    • 是的,先生,我相信您做到了。有人问这个问题:“[使用 ForEach] 有什么好处吗?”,您回答“它很可能更快。”如果您要编辑答案以省略该部分,我当然会撤回我的反对意见。
    【解决方案3】:

    这是对列表中的项目执行操作的更方便的方式/速记,MoreLinq 将此功能扩展到所有实现 IEnumerable 的人。

    【讨论】:

      猜你喜欢
      • 2010-10-19
      • 2012-07-14
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-10-12
      • 2016-02-26
      • 2017-07-14
      • 1970-01-01
      相关资源
      最近更新 更多