簡體   English   中英

C#中IEnumerable類的foreach和for循環之間的區別

[英]Difference between foreach and for loops over an IEnumerable class in C#

有人告訴我,以下代碼塊之間存在性能差異。

foreach (Entity e in entityList)
{
 ....
}

for (int i=0; i<entityList.Count; i++)
{
   Entity e = (Entity)entityList[i];
   ...
}

哪里

List<Entity> entityList;

我不是CLR期望的,但是據我所知,它們應該歸結為基本相同的代碼。 是否有人以一種或另一種方式證明混凝土(哎呀,我要塞滿灰塵)?

foreach創建一個枚舉器的實例(從GetEnumerator返回),並且該枚舉器還在foreach循環的整個過程中保持狀態。 然后,它反復在枚舉器上調用Next()對象,並為返回的每個對象運行代碼。

實際上,它們不會以任何方式簡化為相同的代碼,如果您編寫了自己的枚舉器,您會看到它們。

是一篇很好的文章,顯示了兩個循環之間的IL差異。

從技術上講,Foreach速度較慢,但​​是更易於使用和閱讀。 除非性能至關重要,否則我更喜歡foreach循環而不是for循環。

foreach示例大致與此代碼相對應:

using(IEnumerator<Entity> e = entityList.GetEnumerator()) {
    while(e.MoveNext()) {
        Entity entity = e.Current;
        ...
    }
}

這里有兩個常規的for循環不必支付的費用:

  1. 由entityList.GetEnumerator()分配枚舉數對象的成本。
  2. 列表中每個元素調用兩個虛擬方法(MoveNext和Current)的成本。

這里遺漏了一點:列表具有Count屬性,它在內部跟蹤其中有多少個元素。

IEnumerable不會。

如果您對IEnumerable接口進行編程並使用count擴展方法,它將僅枚舉來對元素進行計數。

有爭議的地方,因為在IEnumerable中您不能按索引引用項目。

因此,如果您想鎖定列表和數組,則性能可能會有所提高。

如果要靈活性,請使用foreach並將其編程為IEnumerable。 (允許使用linq和/或收益率回報)。

在分配方面,最好查看此博客文章 它確切顯示了在什么情況下在堆上分配了枚舉數。

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;
}

我認為,如果可枚舉類型的大小和循環條件為常數,則可能會提高性能,這是一種可能的情況。 例如:

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).

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).

Personally I don't usually worry about it and use foreach any time I need all items and don't care about the index of the item. If I'm not working with all of the items or I really need to know the index, I use for Personally I don't usually worry about it and use foreach any time I need all items and don't care about the index of the item. If I'm not working with all of the items or I really need to know the index, I use for 我唯一看到的最大問題是鏈接列表之類的結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM