29

Every time I need to do something N times inside an algorithm using C# I write this code

for (int i = 0; i < N; i++)
{
    ...
}

Studying Ruby I have learned about method times() which can be used with the same semantics like this

N.times do
    ...
end

Code fragment in C# looks more complex and we should declare useless variable i.

I tried to write extension method which returns IEnumerable, but I am not satisfied with the result because again I have to declare a cycle variable i.

public static class IntExtender
{
    public static IEnumerable Times(this int times)
    {
        for (int i = 0; i < times; i++)
            yield return true;
    }
}

...

foreach (var i in 5.Times())
{
    ...
}

Is it possible using some new C# 3.0 language features to make N times cycle more elegant?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Alexander Prokofyev
  • 33,874
  • 33
  • 95
  • 118

4 Answers4

51

A slightly briefer version of cvk's answer:

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

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

Use:

5.Times(() => Console.WriteLine("Hi"));
5.Times(i => Console.WriteLine("Index: {0}", i));
Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
14

It is indeed possible with C# 3.0:

public interface ILoopIterator
{
    void Do(Action action);
    void Do(Action<int> action);
}

private class LoopIterator : ILoopIterator
{
    private readonly int _start, _end;

    public LoopIterator(int count)
    {
        _start = 0;
        _end = count - 1;
    }

    public LoopIterator(int start, int end)
    {
        _start = start;
        _end = end;
    }  

    public void Do(Action action)
    {
        for (int i = _start; i <= _end; i++)
        {
            action();
        }
    }

    public void Do(Action<int> action)
    {
        for (int i = _start; i <= _end; i++)
        {
            action(i);
        }
    }
}

public static ILoopIterator Times(this int count)
{
    return new LoopIterator(count);
}

Usage:

int sum = 0;
5.Times().Do( i => 
    sum += i
);

Shamelessly stolen from http://grabbagoft.blogspot.com/2007/10/ruby-style-loops-in-c-30.html

cvk
  • 940
  • 6
  • 14
0

I wrote my own extension that add Times to Integer (plus some other stuff). You can get the code here : https://github.com/Razorclaw/Ext.NET

The code is very similar to Jon Skeet answer:

public static class IntegerExtension
{
    public static void Times(this int n, Action<int> action)
    {
        if (action == null) throw new ArgumentNullException("action");

        for (int i = 0; i < n; ++i)
        {
            action(i);
        }
    }
}
Anthony Garcia-Labiad
  • 3,531
  • 1
  • 26
  • 30
0

If you are using .NET 3.5 then you can use the extension method Each proposed in this article, and use it to avoid classic loop.

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

This particular extension method spot welds an Each method on anything that implements IEnumerable. You know this because the first parameter to this method defines what this will be inside the method body. Action is a pre-defined class that basically stands in for a function (delegate) returning no value. Inside the method, is where the elements are extracted from the list. What this method enables is for me to cleanly apply a function in one line of code.

(http://www.codeproject.com/KB/linq/linq-to-life.aspx)

Hope this helps.