Is there an elegant way to repeat an action?

Viewed 53007

In C#, using .NET Framework 4, is there an elegant way to repeat the same action a determined number of times? For example, instead of:

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

I would like to write something like:

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

toRepeat.Repeat(10);

or:

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

I know I can create my own extension method for the first example, but isn't there an existent feature which makes it already possible to do this?

10 Answers

Most convenient I find is:

Enumerable.Range(0, 10).Select(_ => action());

I wrote it as an Int32 extension method. At first I thought maybe that doesn't sound like a good idea, but it actually seems really great when you use it.

public static void Repeat(
   this int count,
   Action action
) {
   for (int x = 0; x < count; x += 1)
      action();
}

Usage:

5.Repeat(DoThing);

value.Repeat(() => queue.Enqueue(someItem));

(value1 - value2).Repeat(() => {
   // complex implementation
});

Note that it will do nothing for values <= 0. At first I was going to throw for negatives, but then I'd always have to check which number is greater when comparing two. This allows a difference to work if positive and do nothing otherwise.

You could write an Abs extension method (either value.Abs().Repeat(() => { }); or -5.RepeatAbs(() => { });) if you wanted to repeat regardless of sign and then the order of the difference of two numbers wouldn't matter.

Other variants are possible as well, like passing the index, or projecting into values similar to Select.

I know there is Enumerable.Range but this is a lot more concise.

If your action is thread-safe you could use

Parallel.For(0, 10, i => myAction(schema));
Related