嵌套的FOR循环:可读性和性能

fla*_*ino 12 c# performance loops for-loop

我理解嵌套的FOR循环.我理解他们做了什么,以及他们是如何做到的.但我的问题是它们对我来说似乎非常难以理解.

举个例子:

for (int i = 0, y = 0; y <= ySize; y++) {
    for (int x = 0; x <= xSize; x++, i++) {
        vertices[i] = new Vector3(x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,这个循环非常简单.它只是一个x/y"二维"循环.但是当我在这个嵌套循环中添加越来越多的"维度"时,有没有办法让代码不是嵌套中的巢和可靠的反向计数变量(i,x,y,z等) ?

另外,额外的嵌套是否会以线性方式影响性能,或者当你嵌套更多的东西时,额外的FORs会使事情变得越来越低效吗?

Ric*_*ett 23

我认为你在这里遇到的问题不是嵌套for循环,而是在循环中更多地使用变量.

开口大括号之前的换行也有助于提高可读性(虽然这是主观的).

怎么样呢:

int i = 0;

for (int y = 0; y <= ySize; y++)
{
    for (int x = 0; x <= xSize; x++)
    {
        vertices[i++] = new Vector3(x, y);
    }
}
Run Code Online (Sandbox Code Playgroud)

对于其他维度,这种方法应该保持相对可读性(在这个例子中,我已经将iout 的递增移动到它自己的行,如usr所建议的那样).

int i = 0;

for (int y = 0; y <= ySize; y++)
{
    for (int x = 0; x <= xSize; x++)
    {
        for (int a = 0; a <= aSize; a++)
        {
            for (int b = 0; b <= bSize; b++)
            {
                vertices[i] = new Vector3(x, y, a, b);

                i++;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

关于性能,我建议重点关注确保代码首先是人类可读和可理解的,然后测量运行时性能,可能使用RedGate ANTS等工具

  • 我甚至会把i ++拉出作业.这就像有人试图压缩试图保存字节的代码. (3认同)
  • @GrimmTheOpiner - 不太正确; 在与[K&R](https://en.wikipedia.org/wiki/Indent_style#K.26R_style)样式相同的行之前将大括号放在同一行上,并在[C语言程序设计语言]中使用](https://en.wikipedia.org/wiki/The_C_Programming_Language)因此受欢迎.我建议(并且更喜欢)的风格显然被称为[Allman风格](https://en.wikipedia.org/wiki/Indent_style#Allman_style). (3认同)

Maa*_*ten 12

通常的解决方案是重构为包含一个或两个for循环的方法,并保持重构直到每个方法都清晰且不太大.

停止缩进以及将循环结果数据与应用逻辑分离的另一种解决方案是使用Linq.

int i = 0;
var coordinates = from y in Enumerable.Range(0, ySize + 1)
                  from x in Enumerable.Range(0, xSize + 1)
                  select new { x, y, i = i++ };

foreach (var coordinate in coordinates) {
    vertices[coordinate.i] = new Vector3(coordinate.x, coordinate.y);
}
Run Code Online (Sandbox Code Playgroud)

仅在vertices已声明数组时才会这样.如果你可以创建一个新数组,那么你可以这样做:

var vertices = (from y in Enumerable.Range(0, ySize + 1)
                from x in Enumerable.Range(0, xSize + 1)
                select new Vector3(coordinate.x, coordinate.y)
               ).ToArray();
Run Code Online (Sandbox Code Playgroud)


usr*_*usr 9

var vertices =
 (from y in Enumerable.Range(0, ySize)
  from x in Enumerable.Range(0, xSize)
  select new Vector3(x, y)).ToList();
Run Code Online (Sandbox Code Playgroud)

循环过度使用.大多数循环可以表示为查询.这使得它们更容易编写和维护,并使它们成为表达式而不是易于移动的语句.

性能要差得多,比如3-10x.这对您的具体情况是否重要取决于此处花费的时间以及您的绩效目标.

  • 好吧,如果我们不想成为那么高水平怎么办?当然,这是一个很好的选择,LINQ.但不是每个人都被迫这样做,如果表现更糟,它不再是一个好的选择. (3认同)
  • 你能否支持表现差3-10倍的说法? (2认同)

isp*_*iro 5

a)通常你会发现你不需要非常深的嵌套,所以这不会是一个问题.

b)您可以将嵌套循环变为单独的方法.(也就是说,如果你嵌套dcba-你可以接受的方法a,并b作为参数和不cd,甚至还可以让VS为你做这个选择的c.循环,然后点击编辑- > Refactor->提取方法)

至于性能 - 显然更多的嵌套意味着更多的迭代,但如果你有它们 - 你需要它们.只是更改一个嵌套循环以包含在原始循环中(以及计算你在"实际"代码中的位置),恕我直言,通常没有任何明显的帮助.