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

Существует ли более короткая/более простая версия цикла for для чего-либо в x раз?

Обычно мы делаем что-то вроде цикла for или while со счетчиком:

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

но иногда вы смешиваете границы. Вместо этого вы можете использовать цикл while, но если вы допустили ошибку, этот цикл будет бесконечным...

В Perl, например, я бы использовал более очевидный

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

Есть ли что-то вроде "doitXtimes (10) {...}"?

4b9b3361

Ответ 1

Ну, вы можете легко написать свой собственный метод расширения:

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

Затем вы можете написать:

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

Я не уверен, что я действительно предлагаю вам это сделать, но это вариант. Я не считаю, что в этой области нет ничего подобного, хотя вы можете использовать Enumerable.Range или Enumerable.Repeat для создания ленивой последовательности соответствующей длины, которая может быть полезна в некоторых ситуациях.


Начиная с С# 6, вы можете получить доступ к статическому методу удобно, не создавая метод расширения, используя директиву using static для его импорта. Например:

// Normally in a namespace, of course.
public class LoopUtilities
{
    public static void Repeat(int count, Action action)
    {
        for (int i = 0; i < count; i++)
        {
            action();
        }
    }
}

Затем, когда вы хотите его использовать:

using static LoopUtilities;

// Class declaration etc, then:
Repeat(5, () => Console.WriteLine("Hello."));

Ответ 2

foreach (var i in Enumerable.Range(0, N))
{
    // do something
}

Ответ 3

Можно создать IEnumerable для Int32:

Enumerable.Range(0, 10);

Метод расширения ForEach также широко известен (хотя и не поставляется с .NET). Вы могли бы объединить два:

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

Таким образом, ваш пример станет следующим:

Enumerable.Range(0, 10).ForEach(_ => list.Add(GetRandomItem()));

Ответ 4

Я вижу Jon Skeet избили меня до него, но этот вариант позволит вам передавать индекс в Action каждый раз, когда он запускается:

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

И назовите его следующим образом:

10.TimesWithIndex((i) =>
            obj[i].DoSomething());

Ответ 5

Пример 1

            var loop = new Loop(50);
            foreach(var index loop) {
                // do something
            }

Пример 2

            foreach(var index in 50.Times().Start(1).Step(-1)) {
                // do something
            }

Пример 3

            var loop = 20.Times();
            while (loop.Do) {
                // do something
            }

Класс и расширение цикла

public class Loop : IEnumerable<int> {

    readonly int times = 0;
    int start = 0;
    int step = 1;
    IEnumerator<int> e;

    public Loop (int times, int start = 0, int step = 1) {
        this.times = times < 0? 0-times : times;
        this.start = start;
        this.step = step;
    }

    public Loop Start(int value) {
        this.start = value;
        return this;
    }

    public Loop Step(int value) {
        this.step = value;
        return this;
    }

    public bool Do {
        get {
            if (this.e.IsNull()) {
                this.e = this.GetEnumerator();
            }
            if (this.e.MoveNext()) {
                return true;
            }
            else {
                this.e.Dispose();
                this.e = null;
                return false;
            }
        }
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return this.GetEnumerator();
    }
    public IEnumerator<int> GetEnumerator() {
        int count = times;
        int value = start;
        while (count != 0) {
            yield return value;
            try {
                value += step;
            }
            catch (OverflowException) {
                break;
            }
            --count;
        }
        yield break;
    }
}

public static class IntLoopExtension {

    public static Loop Times (this int self) {
        return new Loop (self);
    }

}

Ответ 6

while (i-->0) {

}

Вы упомянули, что в то время как цикл опасен, поскольку он может быть бесконечным - вышеупомянутая форма довольно проста и никогда не будет бесконечной. По крайней мере, ПОЛНОСТЬЮ бесконечно:)

Это удобно и коротко (короче любых других ответов) и будет выполняться ровно в я раз (поскольку декремент постфикса возвращает значение до декрементации).