是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
当前回答
这主要是Fortran的遗留问题,在Fortran中,可以将多个语句标签传递给一个函数,这样函数就可以返回其中任何一个。
所以这种代码是完全有效的
CALL SOMESUB(ARG1, 101, 102, 103)
C Some code
101 CONTINUE
C Some more code
102 CONTINUE
C Yet more code
103 CONTINUE
C You get the general idea
但是被调用的函数决定了你的代码路径。有效率呢?可能。可维护的?不。
这就是该规则的来源(顺便说一下,一个函数没有多个入口点,这在fortran和汇编程序中是可能的,但在C中不可能)。
然而,它的措辞看起来像是可以应用到其他语言(关于多个入口点的那个不能应用到其他语言,所以它不是一个真正的程序)。所以这条规则被保留了下来,即使它指的是一个完全不同的问题,而且不适用。
对于更结构化的语言,需要放弃这个规则,或者至少考虑更多。当然,一个充满返回值的函数很难理解,但在开始时返回不是问题。在一些c++编译器中,如果你只从一个地方返回一个值,那么一个返回点可能会生成更好的代码。
但是最初的规则被误解了,被误用了。也不再相关了。
其他回答
使用单一的退出点有好处,就像不可避免的“箭头”编程也有坏处一样。
如果在输入验证或资源分配期间使用多个出口点,我尝试将所有“错误出口”非常明显地放在函数的顶部。
“SSDSLPedia”的Spartan Programming文章和“Portland Pattern Repository’s Wiki”的单一函数出口点文章都对此有一些深刻的争论。当然,还有这篇文章要考虑。
例如,如果您真的需要一个单一的退出点(在任何不支持异常的语言中),以便在一个地方释放资源,我发现仔细应用goto是很好的;请看这个相当做作的例子(压缩以节省屏幕空间):
int f(int y) {
int value = -1;
void *data = NULL;
if (y < 0)
goto clean;
if ((data = malloc(123)) == NULL)
goto clean;
/* More code */
value = 1;
clean:
free(data);
return value;
}
就我个人而言,总的来说,我不喜欢箭头编程,而不喜欢多个出口点,尽管两者在正确应用时都很有用。当然,最好的方法是将程序的结构设计成两者都不需要。将你的函数分解成多个块通常会有所帮助:)
尽管在这样做的时候,我发现我最终得到了多个出口点,就像在这个例子中,一些较大的函数被分解成几个较小的函数:
int g(int y) {
value = 0;
if ((value = g0(y, value)) == -1)
return -1;
if ((value = g1(y, value)) == -1)
return -1;
return g2(y, value);
}
根据项目或编码指南的不同,大多数样板代码可以被宏替换。作为旁注,这样分解可以使函数g0、g1、g2非常容易单独测试。
显然,在面向对象和支持异常的语言中,我不会使用这样的if语句(或者根本不会使用,如果我可以用足够少的努力就能摆脱它的话),代码将更加简单。和non-arrowy。大多数非最终回报可能是例外。
简而言之,
少回报比多回报好 多于一次的返回比巨大的箭头更好,并且保护条款通常是可以的。 在可能的情况下,例外可能/应该取代大多数“保护条款”。
我使用多个出口点使错误情况+处理+返回值尽可能接近。
所以必须测试条件a, b, c必须为真,你需要用不同的方式处理它们:
if (a is false) {
handle this situation (eg. report, log, message, etc.)
return some-err-code
}
if (b is false) {
handle this situation
return other-err-code
}
if (c is false) {
handle this situation
return yet-another-err-code
}
perform any action assured that a, b and c are ok.
a, b和c可能是不同的东西,比如a是输入参数检查,b是新分配内存的指针检查,c是检查参数a中的值。
Structured programming says you should only ever have one return statement per function. This is to limit the complexity. Many people such as Martin Fowler argue that it is simpler to write functions with multiple return statements. He presents this argument in the classic refactoring book he wrote. This works well if you follow his other advice and write small functions. I agree with this point of view and only strict structured programming purists adhere to single return statements per function.
我相信多次返回通常是好的(在我用c#编写的代码中)。单返回样式是从C语言中保留下来的,但是您可能没有用C语言编写代码。
在所有编程语言中,没有法律要求一个方法只有一个退出点。有些人坚持这种风格的优越性,有时他们把它提升为“规则”或“法律”,但这种信念没有任何证据或研究支持。
在C代码中,多个返回样式可能是一个坏习惯,资源必须显式地去分配,但Java、c#、Python或JavaScript等语言具有自动垃圾收集和try. finally块(以及在c#中使用块)等构造,并且这个参数不适用-在这些语言中,需要集中的手动资源回收是非常罕见的。
在某些情况下,单个返回值可读性更好,而在某些情况下则不是这样。看看它是否减少了代码行数,使逻辑更清晰,或减少了大括号、缩进或临时变量的数量。
因此,根据你的艺术感受使用尽可能多的返回,因为这是一个布局和可读性问题,而不是技术问题。
我在我的博客上详细地讨论过这个问题。
唯一重要的问题是“如何使代码更简单、更易读、更容易理解?”如果使用多个返回会更简单,那么就使用它们。