2009-07-23 6 views
3

ジェネリックリストクラスには、.ForEach(Action<T> action)メソッドがあります。今私はいくつかをやっている彼らは両方のパフォーマンスを実行する方法のタイミングと一般的なForEachは貧しいパフォーマーであるようです。.Net - リストはいつですか<T> .ForEachは標準のforeachループよりも優先されますか?

public static class timer{ 
    public static long foreachloop = 0; 
    public static long Gforeachloop = 0;} 

public class something{ 
    public List<string> myStrings = new List<string>(); 

    public something() 
    { 
     for(int i = 1; i<=5000000;i++) 
     { 
      myStrings.Add(i.ToString()); 
     } 
    }} 

public class cls1{ 
    private static List<string> Strings = new List<string>(); 
    private static List<string> OtherStrings = new List<string>(); 

    public static void RunSnippet() 
    { 
     something s = new something(); 

     Stopwatch watch = new Stopwatch(); 
     watch.Start(); 
     foreach(string x in s.myStrings) 
     { 
      Strings.Add(x); 
     } 
     watch.Stop(); 
     timer.foreachloop = watch.ElapsedMilliseconds; 

     watch.Reset(); 
     watch.Start(); 

     s.myStrings.ForEach(delegate(string n){OtherStrings.Add(n);}); 

     s.myStrings.Clear(); 

     watch.Stop(); 
     timer.Gforeachloop = watch.ElapsedMilliseconds; 

     WL("FOREACH-"+timer.foreachloop + ",Count = " + Strings.Count); 
     WL("GFOREACH-"+timer.Gforeachloop + ",Count = " + OtherStrings.Count); 
    } 

    #region Helper methods 

    public static void Main() 
    { 
     try 
     { 
      RunSnippet(); 
     } 
     catch (Exception e) 
     { 
      string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString()); 
      Console.WriteLine(error); 
     } 
     finally 
     { 
      Console.Write("Press any key to continue..."); 
      Console.ReadKey(); 
     } 
    } 

    private static void WL(object text, params object[] args) 
    { 
     Console.WriteLine(text.ToString(), args); 
    } 

    private static void RL() 
    { 
     Console.ReadLine(); 
    } 

    private static void Break() 
    { 
     System.Diagnostics.Debugger.Break(); 
    } 

    #endregion 
} 

FOREACHは177msで、GFOREACHは707msになります。

私はそれを使用する正当な理由があると推測していますが、私はそれを考えることはできません。明らかにパフォーマンスが理由ではないので、いつそれが最良の選択肢になるのかという疑問があります。

ありがとうございます。

+1

関連/ Dupe? http://stackoverflow.com/questions/1172472/when-would-i-use-listt-foreach-over-a-native-foreach-loop – Brandon

答えて

7

エリックリペットからこのブログの記事は、背景を与える:

http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

彼はIEnumerable<T>のために同じことを行うための拡張メソッドの一般的な提案の話だが、哲学的異議が同様に適用されます。

これは、「クール」に見えますが、この方法は決してそんなに良いアイデアではないかもしれないことを示唆しています。 foreachを使用するほうがはっきりしています。

このような方法は、a fix for the classic closure-over-loop-variable bugと考えることができます。

しかし実際には、私はちょうどそのようなバグを発見することでよくなってきました。

+0

彼は主に 'について話します。ForEach'の 'IEnumerable '(ここでは、チェーンや作文を行う)では、リスト内の各オブジェクトに対してメソッドを1行で実行する 'List 'にはありません。 –

+0

しかし、 'IEnumerable 'の 'ForEach'が組み立て可能であるという幅広い合意はありません。明白で一貫した実装では、List .ForEachを模倣して、Ericがブログ記事の例と同じようにvoidを返します。そして、同じ哲学的異論が両方に適用されます。 –

+0

ループ変数クロージャの問題に関しては、匿名の代理人とラムダがループ変数を「スマート」にして、デフォルトでそれらのコピーを取得することを望みました。コーダがラムダの内部からループ変数を変更しようとする非常にまれなケースでは、コーダがラムダの周りをコーディングする可能性があります。残りの99%は、より簡単な生活を送っていました。今修正するのが非常に難しいものの1つ、私は想像しています。おそらく –

6

これはきれいに見えます。

全く冗談ではありません。本当に、私はそれを意味します。あなたの場合にはより読みやすいスタイルで行ってください。たとえば、次のような各項目のメソッドを呼び出すだけの場合:

list.ForEach(Console.WriteLine); 

このスタイルは適切です。しかし、ループの本体として100行がある場合、またはネストされたループと制御フローの構成がある場合は、古いスタイルが良く見えます。

+0

ちょうど私に奇妙に見えます。私は目に見える標準的なforeachをはるかに簡単に使うことができます。 – AnthonyWJones

+0

AnthonyWJones:主に私たちが命令的プログラミングに慣れているからだと思います。このスタイルは、関数型言語を使用しているプログラマには当然のように見えます。 –

+0

@Mehrdad - そうではありません。ハスケルを見てください。副作用を伴う命令コードを書くとき(これはすべてこれに関するものです)、命令型言語のスタイルを模倣する特別なモナド構文を使用します。 –

関連する問題