在.NET中,“ for”或“ foreach”哪个循环运行得更快?


345

在C#/ VB.NET / .NET中,哪个循环运行得更快,for或者foreach

自从我读了一个for循环工程快于foreach环路很久以前我以为这对所有集合,泛型集合,所有阵列,等真正站在

我搜寻了Google并发现了几篇文章,但其中大多数没有定论(阅读文章评论)且开放式。

理想的是列出每个方案,并为它们提供最佳解决方案。

例如(仅作为示例):

  1. 用于迭代1000个以上的字符串数组- for优于foreach
  2. 遍历IList(非通用)字符串- foreachfor

在网上找到了一些相同的参考资料:

  1. Emmanuel Schanzer撰写的原始宏大的旧文章
  2. CodeProject FOREACH与。对于
  3. 博客- foreach是否接受foreach,这是一个问题
  4. ASP.NET论坛-NET 1.1 C#forforeach

[编辑]

除了可读性之外,我对事实和数据真的很感兴趣。在某些应用程序中,压缩性能优化的最后一步很重要。


3
区别仍然存在。特别是在foreach下,数组应该同样快,但是对于其他所有方面,普通循环都更快。当然,在大多数情况下,这没有什么区别,当然,从理论上讲,一个聪明的JIT编译器可以消除这种区别。
jalf

3
没有上下文,我无法确切知道您在做什么,但是当您遇到部分填充的数组时会发生什么?
克里斯·库德莫

6
顺便说一句,每月2百万次点击并不令人恐惧。平均小于每秒命中数。
Mehrdad Afshari,2009年

37
重要说明:昨天这个问题与一个完全无关的问题合并,关于被迫foreach代替forC#使用。如果您在这里看到毫无意义的答案,那就是为什么。责怪主持人,而不是不幸的答案。
TED

7
@TED噢,我想知道所有“您的老板是白痴”的评论从哪里来,谢谢
Gaspa79 2016年

Answers:


350

Patrick Smacchia上个月在博客上发表了以下结论:

  • List上的for循环比List上的foreach循环便宜2倍多。
  • 在数组上循环比在List上循环便宜大约2倍。
  • 结果,使用for循环在数组上循环比使用foreach循环在List上便宜5倍(我相信这是我们所有人所做的)。

129
但是,永远不要忘记:“过早的优化是万恶之源。”
Oorang

18
@Hardwareguy:一旦您知道for几乎快得不可思议,为什么不一般地开始使用它呢?不需要额外的时间。
DevinB,2009年

46
@devinb,使用“ for”比使用“ foreach”困难,因为它添加了代码,另一个变量,您需要检查的条件等。您在“ foreach”循环中看到过一次错误的次数是多少?
tster

35
@Hardwareguy,让我看看我是否明白这一点。遍历一个列表所花的时间foreach比遍历一个遍历一个数组所花的时间长5倍for,而您在调用那个微不足道的内容呢?这种性能差异可能对您的应用程序很重要,也可能无关紧要,但是我不会单枪匹马地消除它。
罗伯特·哈维,

43
通读博客文章,看起来测试是在Debug中运行的,而不是Release中运行的,这可能是有影响的。另外,区别仅在于循环开销。它根本不影响执行循环主体的时间,在大多数情况下,该时间比移至列表的下一个元素所需的时间长得多。这是一个很好的信息,可以让您知道何时确定存在明显的问题,并且已经专门测量了应用程序中的差异,并且有明显的改进,但绝对不是删除所有foreachs的一般建议。
戴维

164

首先,对Dmitry(现已删除)的答案提出反诉。对于数组,C#编译器发出的代码foreach与等效for循环的代码大致相同。这就解释了为什么在此基准测试中结果基本相同:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 1000000;
    const int Iterations = 10000;

    static void Main()
    {
        double[] data = new double[Size];
        Random rng = new Random();
        for (int i=0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }

        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j=0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop: {0}", sw.ElapsedMilliseconds);
    }
}

结果:

For loop: 16638
Foreach loop: 16529

接下来,验证Greg关于集合类型的观点很重要-将上述数组更改为a List<double>,您将获得截然不同的结果。通常,它不仅显着变慢,而且foreach变得比按索引访问显着变慢。话虽如此,我仍然仍然总是喜欢foreach而不是for循环,因为它使代码更简单-因为可读性几乎总是很重要,而微优化却很少。


“在上面将数组更改为List <double>,您将获得截然不同的结果”非常有趣,我没有考虑过
johnc

5
鉴于我的测试与其他基准测试之间的结果存在奇怪的差异,我认为这值得写一篇博客文章……
Jon Skeet

1
在数组和之间,您几乎总是喜欢哪个List<T>?在这种情况下,可读性也胜过微观优化吗?
JohnB

12
@JohnB:是的-我几乎总是喜欢List<T>数组。char[]byte[]是例外,它们通常被视为数据的“块”,而不是正常的集合。
乔恩·斯基特

令人惊讶的是,我的机器上出现了更大的差异,几乎有10%的人赞成在简单阵列上使用foreach。我在疯狂地猜测,所有这些都源于抖动,而不必担心额外的变量,绑定检查等。如果有人对此有深入的解释,这将非常有趣。
塔米尔·丹尼尔

162

foreach循环比for循环展示了更具体的目的

使用foreach循环可以向使用您的代码的任何人证明您计划对集合的每个成员执行某项操作,无论其在集合中的位置如何。它还显示您没有修改原始集合(如果尝试修改,则会引发异常)。

的另一个优点foreach是,它可以在any上工作IEnumerable,其中for仅对有意义IList,其中每个元素实际上都有一个索引。

但是,如果您需要使用元素的索引,那么当然应该允许您使用for循环。但是,如果您不需要使用索引,那么拥有索引只会使您的代码混乱。

据我所知,对性能没有重大影响。在将来的某个阶段,改编代码以foreach使其可以在多个内核上运行可能会更容易,但是现在不必担心。


23
ctford:不,不是。编译器当然不能对中的元素进行重新排序foreachforeach与功能编程完全无关。这完全是编程的当务之急。您将TPL和PLINQ中发生的事情错误地归因于foreach
Mehrdad Afshari,2009年

13
@BlueTrin:当然可以保证排序(C#规范第8.8.4节正式定义foreach为等效while循环)。我想我知道@ctford是指。任务并行库允许基础集合以任意顺序提供元素(通过调用.AsParallel可枚举的元素)。foreach在这里不做任何事情,循环的主体在一个线程上执行。唯一并行化的是序列的生成。
Mehrdad Afshari

6
Enumerable.Select具有一个重载,可让您获取该项目的索引,因此即使需要索引也不要求使用for。请参阅msdn.microsoft.com/en-us/library/bb534869.aspx
TrueWill 2009年

5
ForEach易于阅读,可以保存键入内容。不过,成本很重要;将我制作的文档设计器UI中的2或3个for循环从(对于列表中的每个obj)更改为(对于i = 0到list.count-1),将响应时间从每次编辑的2-3秒减少到了。在一个小型文档上,每次编辑仅需要5秒,就可以循环数百个对象。现在,即使是巨大的文档,也没有太多时间循环播放所有文档。我不知道这是怎么发生的。我所知道的是,替代方案是仅循环对象子集的复杂方案。我每天要花5分钟!- 不是微优化。
FastAl 2011年

5
@FastAl 普通列表之间的差异foreachfor性能之间的差异仅几分之一秒,因此可以遍历数百万个项目,因此您的问题当然与foreach性能没有直接关系,至少与数百个对象没有关系。在您使用的任何列表中,听起来像枚举枚举器实现都是残破的。
Mike Marynowski

53

每当有关于性能的争论时,您只需要编写一个小型测试即可使用定量结果来支持您的案例。

使用StopWatch类,并重复几百万次,以确保准确性。(如果没有for循环,这可能很难):

using System.Diagnostics;
//...
Stopwatch sw = new Stopwatch()
sw.Start()
for(int i = 0; i < 1000000;i ++)
{
    //do whatever it is you need to time
}
sw.Stop();
//print out sw.ElapsedMilliseconds

手指越过此结果表明,这种差异可以忽略不计,您最好还是在可维护性最高的代码中执行任何结果


13
但是您无法比较for和foreach的性能。应该将它们用于不同的环境。
Michael Krelin-黑客

7
我同意您的看法,迈克尔,您不应该根据性能来选择使用哪一种-您应该选择最有意义的一种!但是,如果您的老板说“不要使用它,因为它比foreach速度慢”,那么这是唯一使他相信差异可以忽略的方法
Rob Fonseca-Ensor 2009年

“((如果没有for循环,这可能很难)”,也可以使用while循环。
jonescb

49

它将永远关闭。对于数组,有时 for会更快一些,但foreach更具表现力,并提供LINQ等。通常,请坚持使用foreach

此外,foreach在某些情况下可能会进行优化。例如,链表可能对索引器来说很糟糕,但对链表来说可能很快foreach。实际上,由于LinkedList<T>这个原因,该标准甚至没有提供索引器。


那么,您LinkedList<T>是说比瘦List<T>?而且,如果我始终要使用foreach(而不是for),则最好使用LinkedList<T>吗?
JohnB 2010年

2
@JohnB-不精简;只是不同。例如,链表中的每个节点都有平面数组不需要的其他引用(也支持List<T>)。插入 / 删除更便宜。
马克·格雷韦尔

36

我的猜测是,在99%的情况下它可能并不重要,那么为什么您要选择较快而不是最合适的方法(如最容易理解/维护的方法)?


6
@klew,如果您实际配置了代码,则不必猜测哪20%需要尽可能快。您可能还会发现实际需要快速循环的次数要少得多。此外,您是否真的在说循环的行为是您花费时间的地方,而不是您实际在该循环中所做的事情?
tster

32

两者之间不可能有巨大的性能差异。与往常一样,遇到“哪个更快?” 问题,您应该始终认为“我可以衡量”。

编写两个在循环体内执行相同操作的循环,分别对它们执行和计时,看看速度有何不同。用几乎是空的主体和类似循环的主体来执行此操作。还要尝试使用您使用的集合类型,因为不同类型的集合可能具有不同的性能特征。


32

有充分的理由更喜欢 foreach循环而不是for循环。如果可以使用foreach循环,那么老板应该是对的。

但是,并非每次迭代都只是简单地逐个遍历一个列表。如果他禁止,那是错的。

如果我是你,我会做的就是将所有自然的for循环都转换为递归。那会教给他,对您来说也是一种很好的心理锻炼。


递归与for循环和foreach性能循环相比如何?
JohnB

这取决于。如果您使用尾递归并且编译器足够聪明,可以注意到,那么它可以是相同的。OTOH:如果不这样做,并且您做一些愚蠢的事情,例如将大量不必要的(不变的)数据作为参数传递,或在堆栈上将大型结构声明为局部变量,那可能会非常慢(甚至耗尽RAM)。
TED 2010年

啊 我明白你为什么现在问这个。这个答案引出了一个完全不同的问题。由于种种奇怪的原因,乔纳森·桑普森(Jonathan Sampson)昨天将两者合并。他真的不应该那样做。合并后的答案在这里毫无意义。
TED

18

Jeffrey Richter在TechEd 2005上:

“多年来,我已经开始学习C#编译器对我来说是个骗子。” ..“这取决于很多事情。” ..“就像当您执行一个foreach循环时一样...” ..“ ...那是您编写的一小段代码,但是C#编译器为了做到这一点而吐出的东西却是惊人的。 try / finally块,在finally块内,将变量转换为IDisposable接口,如果转换成功,则在其上调用Dispose方法,在循环内,它在循环内重复调用Current属性和MoveNext方法,对象是在幕后创建的。很多人都使用foreach,因为它非常容易编码,很容易做..“ ..” foreach在性能方面不是很好,

点播网络广播:http : //msevents.microsoft.com/CUI/WebCastEventDetails.aspx? EventID=1032292286& EventCategory=3& culture= en -US&CountryCode= US


12

这是荒唐的。没有令人信服的理由禁止基于性能的循环或其他。

有关性能基准和其他参数,请参见Jon Skeet的博客



更快的循环构造取决于您需要迭代的内容。另一个博客,它对多种对象(例如DataRows和自定义对象)的多次迭代进行了基准测试。它还包括While循环构造的性能,而不仅仅是for和foreach循环构造。
免费编码器24

11

在使用对象集合的情况下,foreach效果更好,但是,如果增加数字,则for循环效果会更好。

请注意,在最后一种情况下,您可以执行以下操作:

foreach (int i in Enumerable.Range(1, 10))...

但它的性能肯定不会更好,实际上与相比,它的性能更差for


“更好”是有争议的:它速度较慢,并且dnspy调试器不会闯入C#foreach(尽管VS2017调试器会)。有时更具可读性,但是如果您不使用这些语言而支持它们,那可能会很烦人。
Zeek2

10

这样可以为您节省:

public IEnumerator<int> For(int start, int end, int step) {
    int n = start;
    while (n <= end) {
        yield n;
        n += step;
    }
}

采用:

foreach (int n in For(1, 200, 4)) {
    Console.WriteLine(n);
}

为了获得更大的胜利,您可以将三个代表作为参数。


1
一个微小的区别是for通常编写循环以排除范围的结尾(例如0 <= i < 10)。Parallel.For也这样做是为了使其易于与公共for循环互换。
Groo 2014年

9

您可以在Deep .NET-第1部分迭代中了解它

它涵盖了.NET源代码一直到反汇编的结果(没有第一次初始化)。

例如-具有foreach循环的数组迭代: 在此处输入图片说明

和-使用foreach循环列出迭代: 在此处输入图片说明

最终结果: 在此处输入图片说明

在此处输入图片说明


8

当遍历数组,列表等常见结构时,for-和-- foreach循环的速度差异很小LINQ,尽管对集合进行查询更好,但对集合进行查询几乎总是慢一些!正如其他海报所言,追求表现力而不是毫秒级的额外表现。

到目前为止,还没有说的是,在foreach编译循环时,编译器会根据要迭代的集合对其进行优化。这意味着,当您不确定要使用哪个循环时,应使用该foreach循环-编译后将为您生成最佳循环。它也更具可读性。

foreach循环的另一个主要优点是,如果您的集合实现发生了变化(例如,从int array变为a List<int>),则您的foreach循环将不需要任何代码更改:

foreach (int i in myCollection)

以上是相同的,无论什么类型的收集,而在你的for循环,如果你改变了下面将不建立myCollectionarrayList

for (int i = 0; i < myCollection.Length, i++)

7

“有什么论据可以帮助我说服他使用for循环吗?”

不,如果您的老板正在对您进行微管理,以告诉您要使用哪种编程语言构造,那么您实在无话可说。抱歉。


7

它可能取决于您要枚举的集合的类型及其索引器的实现。通常,使用foreach可能是更好的方法。

而且,它可以与任何对象一起使用IEnumerable-不仅适用于索引器。


7

这与大多数“更快”的问题具有相同的两个答案:

1)如果您不测量,就不知道。

2)(因为...)这取决于。

对于要迭代的IEnumerable类型,这取决于“ MoveNext()”方法的昂贵程度,相对于“ this [int index]”方法的昂贵程度。

“ foreach”关键字是一系列操作的简写-它在IEnumerable上调用一次GetEnumerator(),在每次迭代中调用一次MoveNext(),进行某种类型检查,依此类推。最有可能影响性能度量的因素是MoveNext()的成本,因为它被调用了O(N)次。也许便宜,但事实并非如此。

“ for”关键字看起来更可预测,但是在大多数“ for”循环中,您会发现类似“ collection [index]”的内容。这看起来像一个简单的数组索引操作,但实际上是一个方法调用,其成本完全取决于要迭代的集合的性质。它可能很便宜,但事实并非如此。

如果集合的基础结构本质上是一个链表,则MoveNext是便宜的,但索引器的成本为O(N),这使“ for”循环的真实成本为O(N * N)。


6

每种语言结构都有适当的使用时间和地点。C#语言有四个独立的迭代语句是有原因的 -每个都有特定的用途,并且有适当的用途。

我建议与您的老板坐下来,并尝试合理地解释为什么for循环有目的。有时for迭代块比foreach迭代更清楚地描述算法。如果是这样,则使用它们是适当的。

我还要向您的老板指出-性能不是问题,也不应该以任何实际的方式成为问题-而是要以简洁,有意义,可维护的方式表达算法。像这样的微优化完全错过了性能优化的要点,因为任何真正的性能优势都将来自算法的重新设计和重构,而不是循环重构。

如果经过理性的讨论,仍然存在这种威权主义的观点,那么如何进行将取决于您。就个人而言,我不会在不鼓励理性思考的环境中工作,并且会考虑转而由另一位雇主担任另一职位。但是,我强烈建议您在沮丧之前进行讨论-可能只是存在一个简单的误解。


5

这是你做了什么内部影响性能比较的循环,而不是实际的循环结构(假设你的情况是不平凡的)。


5

是否forforeach实际要快得多。我严重怀疑,选择一项而不是一项会对您的表现产生重大影响。

优化应用程序的最佳方法是通过分析实际代码。这将查明占用最多工作/时间的方法。首先优化那些。如果性能仍然不能令人满意,请重复该过程。

作为一般规则,我建议您不要进行微优化,因为它们很少会产生任何重大收益。唯一的例外是优化已标识的热路径(即,如果您的性能分析确定了一些使用率很高的方法,则可能有必要对其进行广泛的优化)。


如果我要做的项目中唯一需要做的优化是微优化,那我会很高兴。可悲的是,从来没有这样。
Yannick Motton

2
for比快一点foreach。我会严重反对这一说法。这完全取决于基础集合。如果一个链表类为索引器提供了一个整数参数,我希望for在它上面使用一个循环是O(n ^ 2)而foreach期望是O(n)。
Mehrdad Afshari

@Merhdad:其实这是一个好点。我只是在考虑索引列表(即数组)的常规情况。我会改写以反映这一点。谢谢。
布赖恩·拉斯穆森

@Mehrdad Afshari:由整数索引的集合可能是很多比列举了它慢。但是,您实际上是在将using for indexer查找与使用foreach本身进行比较。我认为@Brian Rasmussen的答案是正确的,除了用于集合之外,它for总是比稍快foreach。但是,for加上集合查找总是比单独查找慢foreach
Daniel Pryden 09年

@Daniel:要么有一个普通的数组,两个数组都将生成相同的代码,要么在使用for语句时涉及一个索引器。for具有整数控制变量的普通循环不能与相比foreach,因此就可以了。我明白@Brian的意思,正如您所说的是正确的,但答案可能会误导您。回复:您的最后一点:不,实际上,for结束List<T>仍然比快foreach
Mehrdad Afshari

4

两者将以几乎完全相同的方式运行。编写一些代码以同时使用它们,然后向他显示IL。它应该显示可比的计算,这意味着性能没有差异。


编译器可以识别在数组/ IList等上使用的foreach循环,并将其更改为for循环。
卡伦·罗杰斯

3
给他看些难以理解的证据证明这是可以的,并要求他证明它不是。
cjk

3

for具有更简单的逻辑实现,因此比foreach更快。


3

除非您处于特定的速度优化过程中,否则我会说使用哪种方法都能产生最容易阅读和维护的代码。

如果已经设置了迭代器(如集合类之一),那么foreach是一个很好的简单选择。如果您要迭代的是整数范围,则for可能更干净。



3

在大多数情况下,实际上没有什么区别。

通常,当您没有显式的数值索引时,您始终必须使用foreach,而在实际上没有可迭代的集合时(例如,在上三角中的二维数组网格上进行迭代),则始终必须使用foreach。 。在某些情况下,您可以选择。

有人可能会争辩说,如果魔术数字开始出现在代码中,则for循环可能会更难维护。您应该因为不能使用for循环而烦恼,而不得不构建一个集合或使用lambda来构建一个子集合,这恰恰是因为禁止了for循环。


3

完全禁止使用诸如for循环之类的东西似乎有些奇怪。

这里有一个有趣的文章在这里涵盖了很多的两个循环之间的性能差异。

我个人会说,我对for循环发现foreach更具可读性,但是如果for循环更合适,那么您应该针对现有工作使用最好的方法,而不必编写额外的长代码以包含foreach循环。


您链接到该文章的基本语录:“ ...如果您打算编写不用于集合的高性能代码,请使用for循环。即使对于集合,使用时foreach看起来也很方便,但效率不高。”
NickFitz

3

我发现foreach循环遍历得List 更快。请在下面查看我的测试结果。在下面的代码中,我array使用forforeach循环分别测量大小为100、10000和100000的an 循环。

在此处输入图片说明

private static void MeasureTime()
    {
        var array = new int[10000];
        var list = array.ToList();
        Console.WriteLine("Array size: {0}", array.Length);

        Console.WriteLine("Array For loop ......");
        var stopWatch = Stopwatch.StartNew();
        for (int i = 0; i < array.Length; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("Array Foreach loop ......");
        var stopWatch1 = Stopwatch.StartNew();
        foreach (var item in array)
        {
            Thread.Sleep(1);
        }
        stopWatch1.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch1.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List For loop ......");
        var stopWatch2 = Stopwatch.StartNew();
        for (int i = 0; i < list.Count; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch2.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch2.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List Foreach loop ......");
        var stopWatch3 = Stopwatch.StartNew();
        foreach (var item in list)
        {
            Thread.Sleep(1);
        }
        stopWatch3.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch3.ElapsedMilliseconds);
    }

更新

在@jgauffin建议之后,我使用了@johnskeet代码,发现forwith 的循环array比下面的循环快,

  • 带数组的Foreach循环。
  • 与列表循环。
  • 带列表的Foreach循环。

请参阅下面的测试结果和代码,

在此处输入图片说明

private static void MeasureNewTime()
    {
        var data = new double[Size];
        var rng = new Random();
        for (int i = 0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }
        Console.WriteLine("Lenght of array: {0}", data.Length);
        Console.WriteLine("No. of iteration: {0}", Iterations);
        Console.WriteLine(" ");
        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with Array: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (var i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with Array: {0}", sw.ElapsedMilliseconds);
        Console.WriteLine(" ");

        var dataList = data.ToList();
        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < dataList.Count; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with List: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in dataList)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with List: {0}", sw.ElapsedMilliseconds);
    }

3
这是一个非常差的测试。a)您进行的迭代次数太少,无法得出结论性的答案。b)Thread.Sleep不会真正等待一毫秒。使用与Jon Skeet回答相同的方法。
jgauffin 2014年

1
肯定有99.99%的时间用在thread.sleep中(这不能保证它将返回的速度,除非至少在那个时间之前不会)。循环非常快,睡眠非常慢,您不必使用后者来测试前者。
罗南·蒂博道


2

我不希望有人在两者之间找到“巨大的”性能差异。

我猜答案取决于您尝试访问的集合是否具有更快的索引器访问实现或更快的IEnumerator访问实现。由于IEnumerator经常使用索引器并且仅保存当前索引位置的副本,因此我希望枚举器访问至少比直接索引访问慢或慢,但不会那么慢。

当然,这个答案并不考虑编译器可能实现的任何优化。


C#编译器几乎没有进行优化,这实际上取决于JITter。
ljs

好吧,JITter是一个编译器...对吗?
JohannesH 2009年

2

请记住,for循环和foreach循环并不总是等效的。如果列表更改,列表枚举器将引发异常,但是您不会总是通过普通的for循环得到该警告。如果列表在错误的时间更改,您甚至可能会得到其他异常。


如果列表从您的下面变出来,则您不能依靠枚举器支持foreach循环来告诉您这一点。在将值返回给您之后导致比赛,它将不再进行检查。
hoodaticus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.