2011-06-20 18 views
28

.NET Framework 4を使用しているC#では、同じアクションを決められた回数繰り返すというエレガントな方法がありますか? 、代わりの例:私は私が最初の例のための私自身の拡張メソッドを作成することができます知っているアクションを繰り返すエレガントな方法はありますか?

Enumerable.Repeat(10,() => 
{ 
    Console.WriteLine("Hello World."); 
    this.DoSomeStuff(); 
}); 

Action toRepeat =() => 
{ 
    Console.WriteLine("Hello World."); 
    this.DoSomeStuff(); 
}; 

toRepeat.Repeat(10); 

か:

int repeat = 10; 
for (int i = 0; i < repeat; i++) 
{ 
    Console.WriteLine("Hello World."); 
    this.DoSomeStuff(); 
} 

私のような何かを書きたいですすでにこれを可能にする既存の機能はありませんか?

答えて

22

これを行うための組み込み方法はありません。

なぜなら、C#は、言語の機能面と命令面との間の分割を強制しようとするからです。 C#は、副作用を起こさない場合にのみ、関数型プログラミングを容易にします。したがって、LINQのWhere,Selectなどのコレクション操作メソッドが得られますが、you do not get ForEachです。

同様に、ここで何をしようとしているのかは、本質的に命令的な行動を表現するいくつかの機能的な方法を見つけることです。 C#ではこれを行うためのツールが提供されていますが、コードをわかりやすく非慣用的にするので、簡単にはできません。

がありますが、IEnumerable<T>.ForEachはありません。 の存在は、フレームワーク設計者が.NET 2.0の時代にこれらの問題を考えていなかったことに起因する歴史的な成果物であると私は言います。明確な部門の必要性は3.0で明らかになっただけです。

+5

もちろん、IEnumerableで独自の副作用を起こす 'Repeat'や' ForEach'メソッドを書くことを止めるものはありません。言語設計者はその時点で手を洗いました。 – geofftnz

+0

「ForEach」を例に挙げると、それはなぜ悪いことなのでしょうか? – Coops

+1

@CodeBlend、それは大きな疑問を投げかけます。 – Joe

26

このようにしますか?

Enumerable.Range(0, 10).ForEach(arg => toRepeat()); 

これは、メソッドを10回実行します。

[編集]

私は私はそれがFCLの一部ではない忘れて、列挙にForEach拡張メソッドを持つことに慣れ。ここで

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) 
{ 
    foreach (var item in source) 
     action(item); 
} 

あなたはForEach拡張メソッドなしで何ができるかです:

Enumerable.Range(0, 10).ToList().ForEach(arg => toRepeat()); 

[編集]

私が最もエレガントな解決策は、再利用可能なメソッドを実装することであると思う:

public static void RepeatAction(int repeatCount, Action action) 
{ 
    for (int i = 0; i < repeatCount; i++) 
     action(); 
} 

使用法:

RepeatAction(10,() => { Console.WriteLine("Hello World."); }); 
+2

古い答えですが、 'Enumerable.Range(0、10).Select(o =>/*返すか何か* /)'を実行することもできます。 –

+1

@ will-hartそれは最初は汚いあなたがしていることを見てください。拡張メソッドを書くことは、アクションを実行するためにselectを悪用する方が良いです。 – Wolfsblvt

7

独自の拡張を展開しないと、私はあなたがこれを行うことが1つのライナーの簡略化のため、この

Action toRepeat =() => { 
     Console.WriteLine("Hello World."); 
     this.DoSomeStuff(); 
    }; 

    int repeat = 10; 
    Enumerable.Range(0, repeat).ToList().ForEach(i => toRepeat()); 
7

ような何かを行うことができますね。わからない何を考える...

Enumerable.Repeat<Action>(() => 
{ 
    Console.WriteLine("Hello World."); 
    this.DoSomeStuff(); 
}, 10).ToList().ForEach(x => x()); 
+2

oこれはエレガントではないと思う。これは、単純なfor文よりも読みにくく、理解しにくいです。 – Ewerton

1
Table table = frame.AddTable(); 
int columnsCount = 7; 

Enumerable.Repeat<Func<Column>>(table.AddColumn, columnsCount) 
      .ToList() 
      .ForEach(addColumn => addColumn()); 
//or 
Enumerable.Range(0, columnsCount) 
      .ToList() 
      .ForEach(iteration => table.AddColumn()); 

これらのオプションがあるためToListメソッド(のエレガントではありません)が、両方は

0

は拡張子を宣言私の場合で働いていた:

public static void Repeat(this Action action, int times){ 
    while (times-- > 0) 
     action.Invoke(); 
} 

次の拡張メソッドを使用できます。

 new Action(() => 
        { 
         Console.WriteLine("Hello World."); 
         this.DoSomeStuff(); 
        }).Repeat(10); 
0
Enumerable.Repeat<Action>(() => { Console.WriteLine("Hello World"); this.DoSomething(); },10); 

エレガントではないですか?