代码之家  ›  专栏  ›  技术社区  ›  mbx

有一个更短/更简单的for循环版本吗?

  •  48
  • mbx  · 技术社区  · 15 年前

    通常我们使用计数器执行for或while循环:

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

    但有时你会混淆界限。你可以用while循环代替,但是如果你犯了错误,这个循环是无限的。。。

    例如,在Perl中,我将使用

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

    有类似“doitXtimes(10){…}”的东西吗?

    7 回复  |  直到 15 年前
        1
  •  64
  •   ToolmakerSteve    8 年前

    你可以很容易地编写自己的扩展方法:

    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 创建适当长度的延迟序列,这在某些情况下非常有用。


    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
  •  44
  •   Grozz    15 年前
    foreach (var i in Enumerable.Range(0, N))
    {
        // do something
    }
    
        3
  •  34
  •   Community Mohan Dere    9 年前

    IEnumerable 国际32:

    Enumerable.Range(0, 10);
    

    这个 ForEach

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

    所以你的例子会变成:

    Enumerable.Range(0, 10).ForEach(_ => list.Add(GetRandomItem()));
    
        4
  •  13
  •   Community Mohan Dere    9 年前

    我看到乔恩·斯凯特了 beat me to it ,但此变体允许您在每次运行操作时将索引传递给该操作:

    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
  •  5
  •   A. Morel    7 年前

    还有一条路不见了:

    List<T> list = System.Linq.Enumerable.Range(0, 10).Select(_ => GetRandomItem()).ToList();
    

    其中T是GetRandomItem()返回的类型

        6
  •  4
  •   Vimes L.B    7 年前
    while (i-- > 0) {
    
    }
    

    你提到虽然循环是危险的,因为它可能是无限的-上述形式是非常简单的,永远不会是无限的。至少是无限的:)

    它既方便又短(比其他任何答案都短),而且可以准确地运行 次数(因为后缀递减返回递减前的值)。

        7
  •  3
  •   ddur    12 年前

    例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);
        }
    
    }
    
    推荐文章