2009-10-27 13 views
6

foreach、performance-wise。ループの前に一度変数を宣言すべきか、ループの内部に変数を宣言すべきですか?

private List<ListItem> GetItems() 
     { 
      var items = new List<ListItem>(); 
      var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
      ListItem item; 
      foreach (var i in collection) 
      { 
       item = new ListItem { Text = i.ToString() }; 
       items.Add(item); 
      } 

      return items; 
     } 

またはこの一例

のための賢明なステートメントのforeach外変数とサイドそれ(foreachの)でそれを再割り当てするたびに宣言するパフォーマンスのためのよりよいまたはforeachの 内の新しい変数を作成しては何ですか?

private List<ListItem> GetItems() 
     { 
      var items = new List<ListItem>(); 
      var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
      foreach (var i in collection) 
      { 
       ListItem item = new ListItem { Text = i.ToString() }; 
       items.Add(item); 
      } 

      return items; 
     } 

ここではアイテムオブジェクトについて詳しく説明します。 ありがとうございます。

答えて

12

premature optimizationのように聞こえます。

まず、パフォーマンス上の問題があると思われる理由はありますか?

第2に、リリースビルドでコンパイラのオプティマイザは、両方のシナリオで同じコードを生成する可能性があります。 - これはおそらく無関係です。デバッグビルドでは、これは常に正しいとは限りませんが、デバッグビルドの目的はコードを正確に進めることができるためです。

4

2つのコードブロックによって生成されたILが同一であることは間違いありません。パフォーマンスに変化はないはずです。しかし、それが使用されている項目のタイプを宣言する2番目のコードブロックは、少し読みやすく、それを使用します。

3

これは非常に微細な最適化であり、両方の方法が同じコードを生成しない場合は、パフォーマンスが正確に同じである可能性が高くなります。この場合は、読みやすいようにしてください。私はあなたのオブジェクトがforeachループの外側で目的を果たさないので、2番目を好むでしょう。

private List<ListItem> GetItems() 
{ 
    var items = new List<ListItem>(); 
    var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

    foreach (var i in collection) 
    { 
    items.Add(new ListItem { Text = i.ToString() }); 
    } 

    return items; 
} 
+0

// prints all items in no particular order foreach (var i in collection) { string s = i.ToString(); ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); }); } 

これは私が何をすべきか通常です。それは自己奉仕だから、私はあなたをアップアップします:D –

0

おそらく同じコードにコンパイルが、なぜそれを再宣言わざわざ:

ほぼ間違いなく、あなたはまた、すべて一緒に記憶された基準を取り除くことができます。 これは参照に関する素晴らしいことです(この場合はアイテムです)。 完了したら、それを別のListItemに割り当てることができ、GC が残りの部分を処理します。

しかし、他のプログラマのための読みやすさ。確かに、アプリケーションのパフォーマンスを大幅に変更することはありません。あなたのケースではさらに良い

0

は次のとおりです。

private List<ListItem> GetItems()   
{    
    var items = new List<ListItem>();    
    var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };    
    foreach (var i in collection)    
     items.Add(new ListItem { Text = i.ToString() });     
    return items;   
} 

なぜ、すべての余分な変数を作成しますか?

1

2つのブロックによって作成されるILは、ほぼ同じである必要があります。あなたが最適化を目指しているのであれば、最終的なリストの長さを項目で埋める前に設定します。そうすれば、リストの長さを伸ばすための拡張ペナルティになることはありません。

ような何か:

private List<ListItem> GetItems() 
    { 
     var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
     var items = new List<ListItem>(collection.Count); //declare the amount of space here 

     foreach (var i in collection) 
     { 
      ListItem item = new ListItem { Text = i.ToString() }; 
      items.Add(item); 
     } 

     return items; 
    } 
0

誰もが推測たように、ILは同じになります。また、他の人が触れたように、問題になるまで、このようなことを心配しないでください。代わりに、その変数のスコープがどこに属しているのかを尋ねてください。

このコードブロックの範囲とコンテキストは、本質的には時期尚早で、このシナリオでは不要な小さなパフォーマンスの最適化よりも重要です。

7

ここにです。変数を匿名メソッド/ lambdaに "取り込む"場合。それ以外の場合は早すぎて違いはありません。まったく。

それは問題でない場合の例:

// may print the same item each time, or any combination of items; very bad 
string s; 
foreach (var i in collection) 
{ 
    s = i.ToString(); 
    ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); }); 
} 
関連する問題