C# の IEnumerable クラスに対する foreach ループと for ループの違い
-
09-06-2019 - |
質問
次のコード ブロック間にはパフォーマンスの違いがあると言われています。
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() オブジェクトを繰り返し呼び出し、返されるオブジェクトごとにコードを実行します。
実際、独自の列挙子を作成した場合にわかるように、これらは結局のところ同じコードにはなりません。
他のヒント
ここ は、2 つのループ間の IL の違いを示す優れた記事です。
Foreach は技術的には遅いですが、はるかに使いやすく、読みやすいです。パフォーマンスが重要でない限り、私は for ループよりも foreach ループを好みます。
foreach サンプルは、次のコードにほぼ対応します。
using(IEnumerator<Entity> e = entityList.GetEnumerator()) {
while(e.MoveNext()) {
Entity entity = e.Current;
...
}
}
通常の for ループでは支払う必要のないコストが 2 つあります。
- entityList.GetEnumerator() によって列挙子オブジェクトを割り当てるコスト。
- リストの各要素に対する 2 つの仮想メソッド呼び出し (MoveNext と Current) のコスト。
ここで 1 つの点が抜けていました:List には Count プロパティがあり、その中に含まれる要素の数を内部的に追跡します。
IEnumerable はそうではありません。
IEnumerable インターフェイスにプログラムし、count 拡張メソッドを使用すると、要素をカウントするためだけに列挙されます。
ただし、IEnumerable ではインデックスで項目を参照できないため、議論の余地があります。
したがって、リストと配列にロックインしたい場合は、パフォーマンスをわずかに向上させることができます。
柔軟性が必要な場合は、foreach を使用し、IEnumerable にプログラムします。(linq および/または yield return の使用を許可します)。
配分に関しては、次のように考えた方がよいでしょう。 このブログ投稿. 。これは、列挙子がどのような状況でヒープに割り当てられるかを正確に示します。
考えられる状況の 1 つとして、 かもしれない 列挙型のサイズとループ条件が定数の場合、パフォーマンスが向上します。例えば:
const int ArraySize = 10;
int[] values = new int[ArraySize];
//...
for (int i = 0; i
この場合、ループ本体の複雑さに応じて、コンパイラはループをインライン呼び出しに置き換えることができる場合があります。.NET コンパイラがこれを行うかどうかはわかりませんが、列挙型のサイズが動的である場合、その有用性は限られています。
ある状況では、 foreach
ランダム アクセスがリストを横断することを意味するリンク リストのようなデータ構造を使用すると、パフォーマンスが向上する可能性があります。によって使用される列挙子 foreach
おそらく、一度に 1 つの項目を反復し、各アクセスが O(1) になり、完全なループが O(n) になりますが、インデクサーを呼び出すことは、先頭から開始して正しいインデックスにある項目を見つけることを意味します。O(n^2) の各ループは O(N) です。
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
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;
}