在C,C ++和C#中使用函数或循环语句中的条件时,可以尽早使用 continue 或 return 语句并删除 if-else 语句的 else 分支。例如:
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
} else {
//do other stuff
}
}
成为
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
continue;
}
//do other stuff
}
和
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
成为
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
如果if-else分支很长,则“after”变体可能更具可读性,因为这种更改消除了else分支的缩进。
这种使用返回/继续是个好主意吗?是否有任何可能的维护或可读性问题?
答案 0 :(得分:31)
我个人选择一种方法的方法是,如果if
部分的主体非常短(最多3或4行),则使用return/continue
变体是有意义的。如果身体很长,跟踪控制流程就更难了,所以我选择else
版本。
因此,通常,此方法将return/continue
样式的使用限制为跳过某些数据并避免进一步处理而不是使用以下方法之一< / em>(if/else
更适合。)
答案 1 :(得分:13)
编译器几乎肯定会生成相同的代码。即使它没有,差异可能是无关紧要的。因此,相关论点肯定是人们如何阅读它。
因此问题是“//做一些东西”和“做其他东西”是多么相似。如果它们在概念上相似,请使用if / else。如果它们在概念上不同,请使用continue / return。
答案 2 :(得分:12)
这取决于分支的长度。如果初始if
检查很短,并且正文很长,那么使用你描述的return / continue是好的。如果if
和else
部分都很长,我会将它们提取为单独的函数。
我建议阅读Code Complete,它会讨论很多这样的事情。
答案 3 :(得分:11)
如果首先处理终止条件,代码将更具可读性。我总是喜欢,检查需要中断或返回的条件而不是那些需要冗长代码执行的条件。 我更喜欢:
if (termination condn)
return;
// code
// code
到
if (success condn)
{
// code
// code
}
else
return;
这使得阅读和理解代码变得更容易。
答案 4 :(得分:6)
巧妙的回答是,这一切都取决于。
我的一般感觉是,如果condition
是罕见的,警卫(例如检查为空)或错误情况,那么我倾向于使用return
或continue
如果这是一个预期的案例,那么我倾向于使用你的第一种方法。
但请注意,我说“倾向”。这些条件之间的界限是模糊的,可能会根据项目和我正在与谁合作而发生变化。
答案 5 :(得分:4)
我通常喜欢
while( loopCondition ) {
if( innerCondition ) {
DoStuff();
} else {
DoOtherStuff();
}
}
如果DoStuff的长度超过了1-2行阈值(并且很容易错过意图),那么继续可能很难跟随。这似乎是将逻辑重构为一些较小方法的好机会。
答案 6 :(得分:4)
不要为了过早优化而牺牲可读性。
例如:
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
在大多数情况下是二进制等效于
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
(即结果代码可能相同)。 但是前者的可读性要好得多,因为你可以清楚地看到代码将是X或Y.
答案 7 :(得分:3)
1)输入或对象状态验证。以下代码:
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
当条件是功能工作的某些要求时,是好的。这是输入验证或对象状态验证的一个阶段。然后,立即使用返回来强调它是正确的,该功能根本没有运行。
2)多级处理。当循环从某个集合中弹出元素并以多级方式处理它们时,/ continue是好的:
while(foo = bar.getNext()) {
if(foo.empty())
continue;
if(foo.alreadyProcessed())
continue;
// Can we take a shortcut?
if(foo.tryProcessThingsYourself())
continue;
int baz = foo.getBaz();
if(baz < 0) {
int qux = foo.getQux();
if(qux < 0) {
// Error - go to next element
continue;
}
}
// Finally -- do the actual processing
baz = baz * 2;
foo.setBaz(baz);
}
该示例显示了在完成一系列多级处理的情况下使用继续是多么自然,此时每个处理都可能被各个地方的各种条件中断。
注意: plinth 发布了真实的例子,它遵循2)所说的内容。
3)一般规则。我使用继续和返回,因为它与某些内容已被中断的事实相对应。当 else 是实际处理的一部分时,我使用 else 。
答案 8 :(得分:2)
一个可能的维护问题是,如果一个函数有多个返回,那么在调试时很难在返回时粘贴一个断点或跟踪。这很少是一个问题,但当你错过一个回归点时,这是一个痛苦。我认为继续循环并不重要,因为循环条件和循环顶部都是唯一的。
除此之外:其他人都在说什么。做什么是最可读的,这取决于“某些东西”和“其他东西”的相对长度,重要性和可能性。更短,更琐碎,更不可能的情况是,它具有特殊情况控制流程的不那么令人不安。
答案 9 :(得分:2)
正如其他人所说,如果事情很短,只能使用return / continue。
我个人只使用continue,如果可以在一行上写,如:
while( loopCondition ) {
if( innerCondition ) continue;
//do other stuff
}
如果在没有代码变得难看的情况下不可能这样写,那么if / else。
答案 10 :(得分:2)
对于笑话,我在我公司的代码库中搜索了“继续”;只是为了了解它的使用位置。我们在一个解决方案中使用59个项目的695次,大约1500个源文件。
我看到它们被使用的主要方式是快速过滤器:
foreach (Frobozz bar in foo) {
if (QuickFilterExclude(bar))
continue;
// extensive processing
}
从预期的例外中恢复:
foreach (Frobozz bar in foo) {
Baz result = new Baz(kDefaultConfiguration);
try {
Baz remoteResult = boo.GetConfiguration();
}
catch (RemoteConnectionException) {
continue;
}
result.Merge(remoteResult);
ReportResult(result);
}
最后是国家机器。
答案 11 :(得分:1)
我跳出一个方法或循环时通常会使用if-return方法,因为没有什么可以做的。
如果身体因为大量工作而更长时间,我建议使用if-else并使用 #region 为块提供一个合理的名称并让它们易于折叠以供人们学习控制流。那个或制作单独的方法:)
答案 12 :(得分:0)
我的代码中有以下内容:
while(){
boolean intersect = doesIntersect(interval_1,interval_2);
if(!intersect){
array.add(interval_2);
if(// another condition){
// Do some thing here
}
continue;
}
// other stuff to do if intersect
}
我是否应该使用继续或使用其他而感到困惑但是我认为内部if条件可能会使其他人无法读取,所以我使用了继续。< / p>
我认为可读性至关重要!