修改FOR循环内的索引变量是不是很好的做法?

时间:2011-02-14 19:58:00

标签: c#

鉴于代码:

for (int i = 1; i <= 5; i++)
        {
            // Do work
        }

从循环中更改i的值是否可以接受? 例如:

for (int i = 1; i <= 5; i++)
        {
            if( i == 2)
            {
               i = 4;
            }
            // Do work
        }

9 个答案:

答案 0 :(得分:10)

在我看来,这太令人困惑了。在这种情况下,最好使用while循环。

答案 1 :(得分:4)

但是,我个人认为应该避免这种情况。由于它创建了大多数开发人员意想不到的代码,我发现它导致了更难以维护的东西。

就个人而言,如果您需要这样做,我建议您切换到while循环:

int i=1;
while (i <= 5)
{
    if (i == 2)
        i = 4;

    ++i;
}

这至少会警告人们你使用的是非标准逻辑。

或者,如果您只是想跳过元素,请使用continue

for (int i = 1; i <= 5; i++)
{
    if (i == 2 || i == 3)
       continue;
}

虽然从技术上讲,除了直接设置i之外,还有一些操作,但对其他开发者来说更​​有意义......

答案 2 :(得分:3)

一个例子是删除符合某些标准的项目:

for (int i = 0; i < array.size(); /*nothing*/)
{
    if (pred(array[i]))
        i++;
    else
        array.erase(array.begin() + i);
}

然而,更好的想法是使用迭代器:

for (auto it = array.begin(); it != array.end(); /*nothing*/)
{
    if (pred(*it))
        ++it;
    else
        it = array.erase(it);
}

修改
哦对不起,我的代码是C ++,问题是关于C#。但不过这个想法是一样的:

for (int i = 0; i < list.Length; /*nothing*/)
{
    if (pred(list[i]))
        i++;
    else
        list.RemoveAt(i);
}

更好的主意当然可能只是

list.RemoveAll(x => !pred(x));

或者稍微更现代的风格,

list = list.Where(pred);

(此处list应为IEnumerable<...>

答案 3 :(得分:2)

您经常在解析数据的应用中看到这种情况。例如,假设我正在扫描二进制文件,而我基本上是在寻找某些数据结构。我可能有代码执行以下操作:

int SizeOfInterestingSpot = 4;
int InterestingSpotCount = 0;
for (int currentSpot = 0; currentSpot < endOfFile; currentSpot++)
{
    if (IsInterestingPart(file[currentSpot])
    {
        InterestingSpotCount++;
        //I know that I have one of what I need ,and further, that this structure in the file takes 20 bytes, so...
        currentSpot += SizeOfInterestingSpot-1;  //Skip the rest of that structure.

    }
}

答案 4 :(得分:1)

我会说是的,但仅限于特定情况。

这可能有点令人困惑 - 如果我设置i=4它会在下一次迭代之前递增吗?

这可能是代码异味的标志 - 也许您之前应该进行LINQ查询并且只处理相关元素?

小心使用!

答案 5 :(得分:1)

是的,它可以。由于存在极其多的可能情况,您必然会发现一个例外,它被视为良好做法。

但是停止理论上的事情,我会说:。不要这样做 它变得非常复杂,难以阅读和/或遵循。我宁愿看到continue语句之类的东西,尽管我也不是那个大粉丝。

答案 6 :(得分:1)

答案 7 :(得分:1)

就个人而言,我会说,如果算法的逻辑需要一个正常线性迭代的行为,但跳过或重复某些迭代,那就去做吧。但是,我也同意大多数人的观点,这对于循环使用来说并不正常,所以我一直在努力,我会确保提出一两行评论,说明为什么会发生这种情况。

这种事情的完全有效的用例可能是解析罗马数字字符串。对于字符串中的每个字符索引,请查看该字符和下一个字符。如果下一个字符的数值大于当前字符,则从下一个字符中减去当前字符的值,将结果添加到总计中,并通过递增当前索引跳过下一个字符。否则,只需将当前字符的值添加到运行总计中并继续。

答案 8 :(得分:0)

引用Petar Minchev:

  

在我看来,这太令人困惑了。   在这种情况下,最好使用while循环。

我会说,通过这样做,您必须意识到可能发生的一些事情,例如无限循环,过早取消的循环,奇怪的变量值或基于您的索引的数学,以及主要(不排除)任何其他的)基于索引的执行流问题和由故障循环修改的其他变量。

但如果你遇到这种情况,那就去吧。