Bin*_*ony 322 .net c# performance for-loop
在C#/ VB.NET/.NET中,哪个循环运行得更快,for或者foreach?
自从我读了一个for循环工程快于foreach环路很久以前我以为这对所有集合,泛型集合,所有阵列,等真正站在
我搜索谷歌并发现了一些文章,但其中大多数都没有结果(阅读文章的评论)和开放式.
什么是理想的是列出每个场景和相同的最佳解决方案.
例如(只是它应该如何的一个例子):
for比...更好foreachIList(非泛型)字符串 - foreach比...更好for在网上找到的一些参考文献:
foreach或不是foreach,这就是问题forvsforeach
[编辑]
除了可读性方面,我对事实和数据非常感兴趣.有些应用程序的最后一英里性能优化受到挤压很重要.
Ian*_*son 328
Patrick Smacchia上个月在博客上写了这个结论,得出以下结论:
- List上的for循环比List上的foreach循环便宜2倍多.
- 在数组上循环比在List上循环便宜约2倍.
- 因此,使用for循环on array比使用foreach在List上循环便宜5倍(我相信,这就是我们所做的).
Jon*_*eet 156
首先,反驳德米特里的答案.对于数组,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);
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
For loop: 16638
Foreach loop: 16529
Run Code Online (Sandbox Code Playgroud)
接下来,验证Greg关于集合类型的重要性 - 将数组更改List<double>为上面的a,您会得到截然不同的结果.它不仅总体上明显变慢,而且foreach变得比通过索引访问慢得多.话虽如此,我仍然总是喜欢foreach到for循环,它使代码更简单 - 因为可读性几乎总是重要的,而微优化很少.
ctf*_*ord 155
foreach循环演示比for循环更具体的意图.
使用foreach循环向使用您的代码的任何人演示,您计划对集合中的每个成员执行某些操作,而不管其在集合中的位置.它还表明您没有修改原始集合(如果您尝试,则会抛出异常).
另一个优点foreach是它适用于任何IEnumerable,for只有在有意义的IList地方,每个元素实际上有一个索引.
但是,如果需要使用元素的索引,那么当然应该允许使用for循环.但是如果你不需要使用索引,那么只有一个索引会使代码混乱.
据我所知,没有重大的性能影响.在未来的某个阶段,使用foreach多个内核运行代码可能更容易,但现在不用担心.
Rob*_*sor 51
任何时候都有关于性能的争论,你只需要编写一个小测试,这样你就可以使用定量结果来支持你的情况.
为了准确,使用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
Run Code Online (Sandbox Code Playgroud)
手指越过了这个节目的结果,差异可以忽略不计,你可能只是在最易维护的代码中做任何结果
Mar*_*ell 49
它总是很接近.对于一个数组,有时 for会稍微快一点,但foreach更具表现力,并提供LINQ等.一般来说,坚持使用foreach.
另外,foreach可以在某些情况下进行优化.例如,链接列表可能是索引器可怕的,但它可能很快foreach.实际上,由于LinkedList<T>这个原因,该标准甚至没有提供索引器.
Bri*_*sen 34
我的猜测是,在99%的情况下它可能不会很重要,那么为什么你会选择更快而不是最合适的(最容易理解/维护)?
Gre*_*ill 30
两者之间不太可能存在巨大的性能差异.一如既往,面对"哪个更快?" 问题,你应该总是想"我可以衡量这一点."
编写两个在循环体中执行相同操作的循环,对它们执行和计时,并查看速度的差异.用一个几乎空的身体和一个类似于你实际做的循环体来做这件事.也可以使用您正在使用的集合类型来尝试它,因为不同类型的集合可以具有不同的性能特征.
T.E*_*.D. 30
有很好的理由喜欢 foreach循环遍历for循环.如果你可以使用foreach循环,你的老板是对的.
但是,并非每次迭代都只是逐个按顺序遍历列表.如果他是禁止的,那是错的.
如果我是你,我会做的就是把所有你自然的循环变成递归.那教会了他,这对你来说也是一种很好的心理锻炼.
Max*_*oro 17
Jeffrey Richter在TechEd 2005上:
"多年来,我开始学习C#编译器对我来说基本上是骗子." ......"它涉及许多事情." .."就像你做一个foreach循环......"......"...这是你编写的一小段代码,但C#编译器为了做到这一点而吐出来的是它的现象.它推出了一个在那里尝试/ finally块,在finally块内部,它将你的变量转换为IDisposable接口,如果转换为suceeds,则调用它上面的Dispose方法,在循环内部,它在循环内部重复调用Current属性和MoveNext方法,在封面下创建了对象.很多人都使用foreach,因为它很容易编码,很容易做到.".."foreach在性能方面不是很好,如果你在一个集合上迭代而不是使用square括号表示法,只是做索引,这只是更快,而且它不会在堆上创建任何对象..."
按需网络直播:http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx? EventID = 1032292286&EventCategory = 3& culture = en -US&CountryCode = US
Rik*_*Rik 12
这是荒唐的.禁止for循环,性能方面或其他方面没有令人信服的理由.
请参阅Jon Skeet的博客,了解性能基准和其他参数.
Met*_*ght 11
如果您使用对象集合,foreach则更好,但如果增加数字,则for循环更好.
请注意,在最后一种情况下,您可以执行以下操作:
foreach (int i in Enumerable.Range(1, 10))...
Run Code Online (Sandbox Code Playgroud)
但它肯定表现不佳,与a相比,它的性能实际上更差for.
aku*_*uhn 10
这应该可以节省你:
public IEnumerator<int> For(int start, int end, int step) {
int n = start;
while (n <= end) {
yield n;
n += step;
}
}
Run Code Online (Sandbox Code Playgroud)
使用:
foreach (int n in For(1, 200, 4)) {
Console.WriteLine(n);
}
Run Code Online (Sandbox Code Playgroud)
为获得更大的胜利,您可以将三名代表作为参数.
当你循环遍历数组,列表等常见结构时,a for和a foreach循环中的速度差异很小,并且LINQ对集合进行查询几乎总是稍微慢一些,尽管写起来更好!正如其他海报所说,追求表现力而不是毫秒的额外表现.
到目前为止还没有说过的是,当foreach编译循环时,编译器会根据迭代的集合对其进行优化.这意味着当你不确定要使用哪个循环时,你应该使用foreach循环 - 它会在编译时为你生成最好的循环.它也更具可读性.
foreach循环的另一个关键优势是,如果您的集合实现发生更改(例如从int array到a List<int>),那么您的foreach循环将不需要任何代码更改:
foreach (int i in myCollection)
Run Code Online (Sandbox Code Playgroud)
无论你的集合是什么类型,上面都是一样的,而在你的for循环中,如果你myCollection从a array变为a ,则不会构建以下内容List:
for (int i = 0; i < myCollection.Length, i++)
Run Code Online (Sandbox Code Playgroud)
这与大多数"更快"的问题具有相同的两个答案:
1)如果你不测量,你不知道.
2)(因为...)取决于.
这取决于"MoveNext()"方法的成本,相对于"this [int index]"方法的成本,对于您将迭代的IEnumerable的类型(或类型).
"foreach"关键字是一系列操作的简写 - 它在IEnumerable上调用GetEnumerator()一次,每次迭代调用一次MoveNext(),它进行一些类型检查,依此类推.最有可能影响性能测量的是MoveNext()的成本,因为它被调用O(N)次.也许它很便宜,但也许不是.
"for"关键字看起来更可预测,但在大多数"for"循环中,您会发现类似"collection [index]"的内容.这看起来像一个简单的数组索引操作,但它实际上是一个方法调用,其成本完全取决于您迭代的集合的性质.可能它很便宜,但也许不是.
如果集合的底层结构本质上是一个链表,那么MoveNext很便宜,但索引器可能有O(N)成本,这使得"for"循环的真实成本为O(N*N).
每种语言结构都有适当的使用时间和地点.C#语言有四个独立的迭代语句是有原因的- 每个语句都有特定用途,并且具有适当的用途.
我建议与老板坐下来,试着理性地解释为什么for循环有目的.有时for迭代块更清楚地描述算法而不是foreach迭代.如果是这样,则使用它们是合适的.
我还要向你的老板指出 - 性能不是,也不应该是任何实际的问题 - 更多的是以简洁,有意义,可维护的方式表达算法.像这样的微优化完全错过了性能优化,因为任何真正的性能优势都来自算法重新设计和重构,而不是循环重构.
如果经过理性的讨论,仍然存在这种威权观点,那么由你来决定如何进行.就个人而言,我不乐意在一个不鼓励理性思考的环境中工作,并考虑转到不同雇主的另一个职位.但是,我强烈建议在讨厌之前进行讨论 - 可能只是存在一个简单的误解.
除了这一点之外,是否for比foreach实际更快.我严重怀疑选择一个会对你的表现产生重大影响.
优化应用程序的最佳方法是通过分析实际代码.这将确定占用大部分工作/时间的方法.首先优化它们.如果性能仍然不可接受,请重复此过程.
作为一般规则,我建议远离微观优化,因为它们很少会产生任何重大收益.唯一的例外是在优化已识别的热路径时(即,如果您的分析确定了一些高度使用的方法,那么广泛优化这些方法可能是有意义的).