C#: 使用List<T>.ForEach(...)与普通的foreach循环相比是否有任何好处?

22

我想知道为什么存在List<T>.ForEach(Action<T>)

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

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

结束

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

?

3个回答

35

.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();
}

3
这是因为在底层,ForEach(Action<T>)使用了一个for循环。在Reflector中,它看起来像这样:for (int i = 0; i < this._size; i++) { action(this._items[i]); }我认为,如果您在循环时插入一个项目到当前位置之前(例如,在位置0处),仍然存在潜在的不稳定结果。 - Ryan Lundy
3
有趣的是,Reflector 还显示微软公司的某个人粗心地从一个名为“match”的 List<T> 方法中剪切并粘贴了空值检查。如果您将 null 作为 Action<T> 参数传递,它会告诉您“match”参数为空,而不是正确的“action”参数。 - Ryan Lundy
1
如此所述:自 .net 4.5 以来,实现已更改,它们“都会抛出异常”。 - Кое Кто

14

很可能更快(你不应该仅因为小的性能优势而选择其中之一,除非你正在处理计算密集型的数值计算或图形应用,并且需要充分利用处理器周期),并且在某些情况下,您可以直接将委托传递给它,这可能是方便的:

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

3
有没有人注意到那个人正在执行1000万次迭代?还谈论着.03秒的节省?在你在这些迭代中进行实际工作的时候,那.03秒可能会有所影响吗? - Ryan Lundy
4
Kyralessa的意思并不是它是否重要。两者之间存在技术上的差异,这对某些人可能很重要。对于回答这个问题来说,这就是唯一重要的。 - Mehrdad Afshari
2
@Gonzalo:ArrayList 没有 ForEach 方法。测试是在比较 List<T>.ForEachList<T> 中的 foreach,同样也适用于数组。 - Mehrdad Afshari
10
这太可笑了。如果在一千万次迭代中节省了0.3秒,谁会在意呢?你在这些迭代中要做什么事情以至于这0.3秒的差别就显得那么重要呢?这是一个有趣的好奇心,但实际上没有任何现实价值。编写容易阅读的代码,使用最符合人类阅读程序的循环结构。如果你真的需要节省0.3秒,你应该首先用C或C++编写程序,而不是C#或VB .NET。 - Ryan Lundy
3
是的先生,我相信您说过这句话。问题是:“使用 ForEach 有什么好处?”,你回答说:“很可能会更快。”如果你编辑你的回答把这一部分去掉,我肯定会撤回我的异议。 - Ryan Lundy
显示剩余6条评论

0

使用这种方法/速记法更方便地在列表中执行操作,MoreLinq 扩展了所有实现 IEnumerable 的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接