繁体   English   中英

为什么是List <T> .ForEach比标准foreach更快?

[英]Why is List<T>.ForEach faster than standard foreach?

考虑一下:

必要的:

//The alphabet from a-z
List<char> letterRange = Enumerable.Range('a', 'z' - 'a' + 1)
.Select(i => (Char)i).ToList(); //97 - 122 + 1 = 26 letters/iterations

标准foreach:

foreach (var range in letterRange)
{
    Console.Write(range + ",");
}
Console.Write("\n");

内置的foreach:

letterRange.ForEach(range => Console.Write(range + ",")); //delegate(char range) works as well
Console.Write("\n");

我已经尝试过将它们相互对准,并且内置的foreach速度提高了2倍,这似乎很多。

我用Google搜索了,但我似乎无法找到任何答案。

另外,关于: 在.NET中,哪个循环运行得更快,'for'或'foreach'?

for (int i = 0; i < letterRange.Count; i++)
{
    Console.Write(letterRange[i] + ",");
}
Console.Write("\n");

据我所知,不执行比标准foreach更快。

我认为你的基准是有缺陷的。 Console.Write是一个I / O绑定任务,它是您的基准测试中最耗时的部分。 这是一个微观基准,应该非常仔细地进行,以获得准确的结果。

这是一个基准: http//diditwith.net/PermaLink,guid,506c0888-8c5f-40e5-9d39-a09e2ebf3a55.aspx (看起来不错,但我自己没有验证过)。 截至2015年8月14日,该链接似乎已被破坏

当您输入foreach循环时,您将枚举每个项目。 该枚举导致每次迭代两次方法调用:一次到IEnumerator<T>.MoveNext() ,另一次到IEnumerator<T>.Current 这是两个call IL指令。

List<T>.ForEach更快,因为它每次迭代只有一个方法调用 - 无论你提供的Action<T>委托是什么。 这是一个callvirt IL指令。 这明显快于两个call指令。

正如其他人所指出的那样,像Console.WriteLine()这样的IO绑定指令会污染你的基准测试。 做一些可以完全局限于记忆的事情,比如将序列的元素添加到一起。

这是因为foreach方法没有使用枚举器。 枚举器(foreach)往往比基本for循环慢:

这是ForEach方法的代码:

public void ForEach(Action<T> action)
{
    if (action == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        action(this._items[i]);
    }
}

虽然我希望有所不同,但我有点惊讶它和你指出的一样大。 使用枚举器方法,您将创建额外的对象,然后采取额外的步骤以确保枚举器不会失效(集合已被修改)。 您还需要通过一个额外的函数调用Current()来获取该成员。 这一切都增加了时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM