最近,我正在查看一个开源项目,虽然我已经使用.NET开发了几年,但我之前从未遇到过continue
关键字。
问题: 有哪些最佳实践或领域可以从使用continue
关键字中受益?我之前为什么可能没有看到它?
使用它可以立即退出当前循环迭代并开始下一个迭代,如果适用的话。
foreach (var obj in list)
{
continue;
var temp = ...; // this code will never execute
}
continue
通常与一个条件相关联,而该条件通常可以代替continue
。
foreach (var obj in list)
{
if (condition)
continue;
// code
}
可以简单地写成
foreach (var obj in list)
{
if (!condition)
{
// code
}
}
continue
如果你的循环体内有多层嵌套的if
逻辑时,可能会变得更加吸引人。使用continue
而不是嵌套可以使代码更易读。当然,重构循环和条件语句为适当的方法也会使循环更易读。
continue
关键字用于跳过循环块的其余部分并继续执行。例如:
for(int i = 0; i < 5; i++)
{
if(i == 3) continue; //Skip the rest of the block and continue the loop
Console.WriteLine(i);
}
会输出:
0
1
2
4
它可以防止深层嵌套。
foreach(var element in collection)
{
doSomething();
doSomethingElse();
if (condition1)
{
action1();
action2();
if (condition2)
{
action3();
}
}
}
可以重写为
foreach(var element in collection)
{
doSomething();
doSomethingElse();
if (!condition1)
{
continue;
}
action1();
action2();
if (!condition2)
{
continue;
}
action3();
}
如果代码块不是简单的垂直大小,使用 continue
可以提高代码的可读性。显然,与任何其他语言结构一样,应该慎重使用。
当您不想从循环中break
出来,但您需要进行下一次迭代:
for (int i = 0; i < something; i++)
{
if (condition)
continue;
// expensive calculations, skip due to continue
// or due to the condition above I don't want to
// run the following code
stuff();
code();
}
你应该节制使用它。
最好(即易于阅读)的循环不使用break
或continue
,它们是一种结构化的goto语句。
话虽如此,1或2个break/continue
语句并不会使循环难以阅读,但明确使用它们并保持简单是值得的。
基本上,continue
和break
是更好的(但经常只是伪装的)goto
语句...
每当你在循环内部,并且知道接下来的所有内容都应该被跳过,并继续下一次迭代时,你可以使用continue
...
因此,它们应该很少使用...有时它们使代码非常易读和清晰(例如,如果替代方案是几个层次的嵌套)...大多数时候它们会增加一些类似于goto
的混乱。
continue
有点类似于goto
、break
以及函数中的早期return
。我们都知道Goto被认为是有害的,因此许多开发人员可能会避免使用它。continue
。通过使用continue
,我可以跳过这些值,而无需将我的循环中“重要”的逻辑嵌套在一个嵌套的if
中。foreach (var v in GetSomeValues())
{
if (ThisValueIsNotImportant(v)) continue;
//Do important stuff with the value.
}
while(!SomeQueue.Empty)
{
byte nextByte = SomeQueue.Dequeue();
switch State:
{
case A:
if(nextByte == Condition)
{
State = B;
}
else
{
State = ParseError;
}
continue;
case B:
//Test nextByte
State = C;
continue;
case C:
//Test nextByte
State = A;
continue;
case ParseError:
//Do something for this condition
State = A;
continue;
}
如果我没有使用它,我会错过什么吗?
这似乎是一个奇怪的问题。你应该比任何其他人都更清楚是否需要提前开始下一次循环。
不推荐使用continue语句(或尽可能重构以删除它)的几个主要原因:
continue
,那么你所使用的循环会处理列表中不需要查看的元素。现在随着Jitted编译器或像Java、C#这样的VM系统,编译器通常会简化和重构列表。但是仍然可能会增加内存,因为额外的对象可能被存储。低级语言将受到巨大的打击。重构你的循环语句,只循环需要受影响的元素。continue
(还有较小程度上的'break'),你正在使两行代码负责循环逻辑,更糟糕的是:continue语句可以出现在循环内部的任何位置(见下一点)。一些例子:
不必要地使用continue语句循环未使用的项目:
foreach(var item in list) {
if(item.param3 == "hippies") continue;
//edit the item here
}
重构后(使用更少的内存和CPU):
foreach(var item in list.Where(x => x.param3 != "hippies")) {
//edit item here
}
continue用于仅更新列表项的某些部分。
for(var item in itemList) { //must always be checked with any object change
item.param1 = 45;
item.param2 = "this is a thing";
if(item.param3 == "hippies") continue; //must be checked with any object code change
item.param3 = "dodgy code"
DoThisCode(item);
}
newParam
,循环现在应该只在newParam满足某个条件且param3不等于hippies时执行某些操作。更新的人必须知道continue正在使用并正确更新它,同时检查循环条件并确保它是正确的,即使它可能陈述了与他们所寻找的相反的内容(param3 ==“hippies”而不是!=“hippies”或另一组值)。foreach(var item in list) {
if(item.param1 == condition)
{
someChangesMadeToItem(item);
}
else if(item.param3 == condition)
{
someMoreChangesMadeToItem(item);
}
//another 5-6 lines of code.
if(item.param2 == condition) {
continue;
}
someMoreChangesMadeToItem(item);
//another 20+ lines of code here
result.add(item);
}
return result;
continue
解决的情况。 - neontapir