tags:

views:

204

answers:

4

Usually we do something like a for or while loop with a counter:

for (int i = 0; i < 10; i++)
{
    list.Add(GetRandomItem());
}

but sometimes you mix up with boundaries. You could use a while loop instead, but if you make a mistake this loop is infinite...

In Perl for example I would use the more obvious

for(1..10){
    list->add(getRandomItem());
}

Is there something like "doitXtimes(10){...}"?

+11  A: 

Well you can easily write your own extension method:

public static void Times(this int count, Action action)
{
    for (int i = 0; i < count; i++)
    {
        action();
    }
}

Then you can write:

10.Times(() => list.Add(GetRandomItem()));

I'm not sure I'd actually suggest that you do that, but it's an option. I don't believe there's anything like that in the framework, although you can use Enumerable.Range or Enumerable.Repeat to create a lazy sequence of an appropriate length, which can be useful in some situations.

Jon Skeet
Would be nice to have some syntax for that without the extra "() =>" =)
Yacoder
@Yacoder: No, it wouldn’t, because then the meaning of the code would be ambiguous.
Timwi
@Timwi: I think Yacoder means a completely different syntax, maybe using blocks as in Ruby for instance. Not just writing `10.Times(list.Add(GetRandomItem()));`, which indeed would be very annoying and ambiguous (for both humans and compilers).
haylem
@Yacoder: If @haylem is right, well then any syntax you can come up with is just a replacement for `() =>`, which I think is already short enough.
Timwi
@Yacoder: Well, in this case you could use `10.Times(delegate{ list.Add(GetRandomItem()); });` but that's even more muddled, imo.
LukeH
@Timwi -- of course, it must not be ambiguous =)
Yacoder
You just need to express that you're not calling this method on list, but rather passing this call as a lambda... maybe something like `list -> Add(GetRandomItem())`... don't know, it's just an idea, which could make this code better readable (hopefully)
Yacoder
Thanks. This exactly meets my demands.
mbx
+6  A: 

One can create an IEnumerable of Int32:

Enumerable.Range(0, 10);

The ForEach extension method is also widely known (although not shipped with .NET). You could combine the two:

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

So your example would become:

Enumerable.Range(0, 10).ForEach(_ => list.Add(GetRandomItem()));
Paul Ruane
Although this works, it's not quite handy.
mbx
@mbx: Yes, Jon Skeet's Times method is much better when the index is not required and you just want to repeat an operation.
Paul Ruane
+2  A: 
foreach (var i in Enumerable.Range(0, N))
{
    // do something
}
Grozz
This version is nice, when you need the index.
mbx
A: 

I see Jon Skeet beat me to it, but this variation will allow you to pass the index to the Action each time it is run:

public static class IntegerExtensions
{
   public static void TimesWithIndex(this int count, Action<int> action)
  {
     for (int i = 0; i < count; i++)
        action(i);
  }
}

And call it like this:

10.TimesWithIndex((i) =>
            object[i].DoSomething());
Alex Baranosky