Подтвердить что ты не робот

Любые шансы подражать временам() Ruby-метод в С#?

Каждый раз, когда мне нужно делать что-то N раз в алгоритме с использованием С#, я пишу этот код

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

Изучение Ruby Я узнал о методе times(), который может использоваться с той же семантикой, что и этот

N.times do
    ...
end

Кодовый фрагмент в С# выглядит более сложным, и мы должны объявить бесполезную переменную i.

Я попытался написать метод расширения, который возвращает IEnumerable, но я не удовлетворен результатом, потому что снова мне нужно объявить циклическую переменную 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())
{
    ...
}

Возможно ли использование некоторых новых функций языка С# 3.0, чтобы сделать цикл N более элегантным?

4b9b3361

Ответ 1

Немного более краткий вариант cvk 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);
        }
    }
}

Использование:

5.Times(() => Console.WriteLine("Hi"));
5.Times(i => Console.WriteLine("Index: {0}", i));

Ответ 2

Это действительно возможно с С# 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);
}

Использование:

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

Бесстыдно украден из http://grabbagoft.blogspot.com/2007/10/ruby-style-loops-in-c-30.html

Ответ 3

Если вы используете .NET 3.5, вы можете использовать метод расширения. Каждый из предложенных в этой статье и использовать его, чтобы избежать классического цикла.

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

Этот конкретный метод расширения сваривает каждый метод на все, что реализует IEnumerable. Вы знаете это потому, что первый параметр этот метод определяет, что это будет внутри способ корпус. Действие - это предопределенный класс, который в основном выступает за функцию (делегат) не возвращая никакой ценности. Внутри метода, где элементы извлекаются из списка. Что этот метод Это позволяет мне четко применять функция в одной строке кода.

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

Надеюсь, что это поможет.

Ответ 4

Я написал собственное расширение, которое добавляет Times to Integer (плюс некоторые другие вещи). Вы можете получить код здесь: https://github.com/Razorclaw/Ext.NET

Код очень похож на ответ Джона Скита:

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);
        }
    }
}