我被告知以下代码块之间存在性能差异。
foreach (Entity e in entityList)
{
....
}
和
for (int i=0; i<entityList.Count; i++)
{
Entity e = (Entity)entityList[i];
...
}
,其中
List<Entity> entityList;
我不是CLR的期望,但从我可以告诉他们应该归结为基本相同的代码。是否有人有这样或那样的混凝土(哎呀,我会把包装好的污垢)证据?
答案 0 :(得分:10)
foreach创建一个枚举器的实例(从GetEnumerator返回),该枚举器在整个foreach循环过程中也保持状态。然后它重复调用枚举器上的Next()对象,并为它返回的每个对象运行代码。
他们不会以任何方式归结为相同的代码,实际上,如果您编写自己的枚举器,就会看到它。
答案 1 :(得分:9)
Here是一篇很好的文章,显示了两个循环之间的IL差异。
Foreach在技术上较慢,但更容易使用且更易于阅读。除非性能至关重要,否则我更喜欢fore循环而不是for循环。
答案 2 :(得分:6)
foreach示例大致对应于此代码:
using(IEnumerator<Entity> e = entityList.GetEnumerator()) {
while(e.MoveNext()) {
Entity entity = e.Current;
...
}
}
这里有两个成本,常规for循环不需要支付:
答案 3 :(得分:3)
这里错过了一点: List具有Count属性,它在内部跟踪其中有多少元素。
IEnumerable没有。
如果编程到IEnumerable接口并使用count extention方法,它将枚举只计算元素。
虽然因为在IEnumerable中你不能通过索引引用项目,所以有点没有实际意义。
因此,如果你想锁定Lists and Arrays,你可以获得较小的性能提升。
如果你想要灵活性,可以使用foreach和program to IEnumerable。 (允许使用linq和/或收益率)。
答案 4 :(得分:1)
在分配方面,最好看this blogpost。它完全显示了在堆上分配枚举数的情况。
答案 5 :(得分:0)
我认为可能获得性能提升的一种可能情况是,可枚举类型的大小和循环条件是否为常量;例如:
const int ArraySize = 10;
int[] values = new int[ArraySize];
//...
for (int i = 0; i
In this case, depending on the complexity of the loop body, the compiler might be able to replace the loop with inline calls. I have no idea if the .NET compiler does this, and it's of limited utility if the size of the enumerable type is dynamic.
One situation where foreach
might perform better is with data structures like a linked list where random access means traversing the list; the enumerator used by foreach
will probably iterate one item at a time, making each access O(1) and the full loop O(n), but calling the indexer means starting at the head and finding the item at the right index; O(N) each loop for O(n^2).
foreach
。我唯一能看到它是一个大问题的是链接列表等结构。
答案 6 :(得分:0)
For Loop
for loop is used to perform the opreration n times
for(int i=0;i<n;i++)
{
l=i;
}
foreach loop
int[] i={1,2,3,4,5,6}
foreach loop is used to perform each operation value/object in IEnumarable
foreach(var k in i)
{
l=k;
}