我应该使用return / continue语句而不是if-else吗?

在C,C ++和C#中,当在函数或循环语句中使用条件时,可以尽早使用continuereturn语句,并删除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分支的缩进。

是这样使用返回/继续一个好主意? 是否有任何可能的维护或可读性问题?

编译器几乎肯定会生成相同的代码。 即使它没有,差异可能是无关紧要的。 因此,相关的论点当然是人们如何阅读它。

因此问题是“//做一些东西”和“做其他东西”是多么相似。 如果它们在概念上相似,请使用if / else。 如果它们在概念上不同,请使用continue / return。

我个人选择一种方法的方法是,如果if部分的主体非常短(最多3或4行),则使用return/continue变体是有意义的。 如果身体很长,那么跟踪控制流程就更难了,所以我选择了else版本。

因此,通常,此方法限制了return/continue样式的使用以跳过某些数据并避免进一步处理,而不是使用以下方法之一处理此方法if/else更适合)。

这取决于分支的长度。 如果初始if检查很短,并且正文很长,那么使用你描述的return / continue是好的。 如果ifelse部分都很长,我会将它们提取为单独的函数。

我建议阅读Code Complete,它会讨论很多这样的事情。

如果首先处理终止条件,则代码将更具可读性。 我总是喜欢,检查需要中断或返回的条件而不是那些需要冗长代码执行的条件。 我更喜欢:

  if (termination condn) return; // code // code 

 if (success condn) { // code // code } else return; 

这使得阅读和理解代码更容易。

巧妙的回答是,这一切都取决于。

我的一般感觉是,如果condition是罕见的,保护(例如检查为空)或错误条件,那么我倾向于使用returncontinue

如果这是一个预期的案例,那么我倾向于使用你的第一种方法。

但请注意,我说“倾向”。 这些条件之间的界限是模糊的,可能会根据项目和我正在与谁合作而变化。

我通常喜欢

 while( loopCondition ) { if( innerCondition ) { DoStuff(); } else { DoOtherStuff(); } } 

如果DoStuff的长度超过1-2行阈值(并且很容易错过意图),则很难继续。 这似乎是将逻辑重构为一些较小方法的好机会。

不要为了过早优化而牺牲可读性。

例如:

 void function() { if( condition ) { //do some stuff } else { //do other stuff } } 

在大多数情况下二进制等价于

 void function() { if( condition ) { //do some stuff return; } //do other stuff } 

(即结果代码可能是相同的)。 但是前者的可读性要好得多,因为你可以清楚地看到代码将是X或Y.

1) 输入或对象状态validation 。 以下代码:

 void function() { if( condition ) { //do some stuff return; } //do other stuff } 

当条件是function工作的某些要求时,这是好的。 这是输入validation或对象状态validation的一个阶段。 然后,立即使用返回来强调它是正确的,该function根本没有运行。

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) 一般规则 。 我使用continue返回,因为它与某些事物被中断的事实相对应。 当else是实际处理的一部分时,我使用else

一个可能的维护问题是,如果一个函数有多个返回,那么在调试时很难在返回时粘贴断点或跟踪。 这很少是一个问题,但当你错过一个回归点时,这是一个痛苦。 我认为继续循环并不重要,因为循环条件和循环顶部都是唯一的。

除此之外:其他人都在说什么。 做什么是最可读的,这取决于“某些东西”和“其他东西”的相对长度,重要性和可能性。 更短,更琐碎,更不可能的情况是,它具有特殊情况控制流程的不那么令人不安。

正如其他人所说,如果事情很短,只能使用return / continue。

我个人只使用continue,如果可以在一行上写,如:

 while( loopCondition ) { if( innerCondition ) continue; //do other stuff } 

如果在没有代码变得丑陋的情况下不可能这样写,那么if / else。

为了笑容,我在我公司的代码库中搜索了“继续”; 只是为了了解它的使用位置。 我们在一个解决方案中使用59个项目的695次,大约1500个源文件。

我看到它们被使用的主要方式是作为快速filter:

 foreach (Frobozz bar in foo) { if (QuickFilterExclude(bar)) continue; // extensive processing } 

从预期的exception中恢复:

 foreach (Frobozz bar in foo) { Baz result = new Baz(kDefaultConfiguration); try { Baz remoteResult = boo.GetConfiguration(); } catch (RemoteConnectionException) { continue; } result.Merge(remoteResult); ReportResult(result); } 

最后是国家机器。

跳出方法或循环时,我通常使用if-return方法,因为没有什么可以做的。

如果身体因为大量工作而更长,我建议使用if-else并且可能使用#region为块提供合理的名称并让它们容易折叠以供人们研究控制流程。 那个或制作单独的方法:)

我的代码中有以下内容:

  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条件可能使其他人不能很好阅读,所以我用继续。

我认为可读性才是最重要的!