是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
当前回答
作为嵌套if的替代方法,有一种使用do/while(false)在任何地方爆发的方法:
function()
{
HRESULT error = S_OK;
do
{
if(!SUCCEEDED(Operation1()))
{
error = OPERATION1FAILED;
break;
}
if(!SUCCEEDED(Operation2()))
{
error = OPERATION2FAILED;
break;
}
if(!SUCCEEDED(Operation3()))
{
error = OPERATION3FAILED;
break;
}
if(!SUCCEEDED(Operation4()))
{
error = OPERATION4FAILED;
break;
}
} while (false);
return error;
}
这为您提供了一个出口点,允许您进行其他嵌套操作,但仍然不是真正的深层结构。如果你不喜欢成功,你可以做任何失败的事情。这类事情还允许您在任意两个其他检查之间添加其他代码,而无需重新缩进任何内容。
如果你真的疯了,整个If块也可以宏化。: D
#define BREAKIFFAILED(x,y) if (!SUCCEEDED((x))) { error = (Y); break; }
do
{
BREAKIFFAILED(Operation1(), OPERATION1FAILED)
BREAKIFFAILED(Operation2(), OPERATION2FAILED)
BREAKIFFAILED(Operation3(), OPERATION3FAILED)
BREAKIFFAILED(Operation4(), OPERATION4FAILED)
} while (false);
其他回答
我想说的是,你应该有尽可能多的需要,或者任何使代码更干净的(如保护子句)。
我个人从来没有听过/见过任何“最佳实践”说你应该只有一个返回语句。
在大多数情况下,我倾向于根据逻辑路径尽快退出函数(保护子句就是一个很好的例子)。
正如Kent Beck在《实现模式》中讨论保护子句时指出的那样,使一个例程具有单一的入口和出口点……
是为了防止可能的混淆 当你在许多地方跳来跳去 同一例程中的位置。这让 当应用到FORTRAN或 汇编语言程序 有大量的全球数据,甚至 理解哪些语句是 执行是一项艰苦的工作……使用小方法和大部分本地数据,它是不必要的保守。”
我发现用保护子句编写的函数要比一长串嵌套的if then else语句容易理解得多。
如果你最终得到了很多返回值,那么你的代码可能有问题。否则,我同意有时能够从子例程的多个位置返回是很好的,特别是当它使代码更干净的时候。
Perl 6:坏例子
sub Int_to_String( Int i ){
given( i ){
when 0 { return "zero" }
when 1 { return "one" }
when 2 { return "two" }
when 3 { return "three" }
when 4 { return "four" }
...
default { return undef }
}
}
这样写会更好吗
Perl 6:好例子
@Int_to_String = qw{
zero
one
two
three
four
...
}
sub Int_to_String( Int i ){
return undef if i < 0;
return undef unless i < @Int_to_String.length;
return @Int_to_String[i]
}
注意,这只是一个简单的例子
在其他条件相同的情况下,单一出口点可以显著提高代码的可读性。 但有一个问题:流行的结构
resulttype res;
if if if...
return res;
是假的,“res=”不比“return”好多少。它只有一个return语句,但函数实际结束的地方有多个点。
如果你的函数有多个返回值(或“res=”s),最好将它分解成几个较小的函数,每个函数都有一个退出点。
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
是的,有:
The single exit point gives an excellent place to assert your post-conditions. Being able to put a debugger breakpoint on the one return at the end of the function is often useful. Fewer returns means less complexity. Linear code is generally simpler to understand. If trying to simplify a function to a single return causes complexity, then that's incentive to refactor to smaller, more general, easier-to-understand functions. If you're in a language without destructors or if you don't use RAII, then a single return reduces the number of places you have to clean up. Some languages require a single exit point (e.g., Pascal and Eiffel).
这个问题通常被提出为多个返回或深度嵌套的if语句之间的错误二分法。几乎总有第三种解决方案,它是线性的(没有深度嵌套),只有一个出口点。
更新:MISRA的指导方针显然也提倡单次退出。
需要澄清的是,我并不是说拥有多个回报总是错误的。但如果有其他等价的解决方案,有很多很好的理由选择单一回报的方案。