鉴于代码:
for (int i = 1; i <= 5; i++)
{
// Do work
}
从循环中更改i
的值是否可以接受?
例如:
for (int i = 1; i <= 5; i++)
{
if( i == 2)
{
i = 4;
}
// Do work
}
答案 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循环。
我会说,通过这样做,您必须意识到可能发生的一些事情,例如无限循环,过早取消的循环,奇怪的变量值或基于您的索引的数学,以及主要(不排除)任何其他的)基于索引的执行流问题和由故障循环修改的其他变量。
但如果你遇到这种情况,那就去吧。