是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
当前回答
在其他条件相同的情况下,单一出口点可以显著提高代码的可读性。 但有一个问题:流行的结构
resulttype res;
if if if...
return res;
是假的,“res=”不比“return”好多少。它只有一个return语句,但函数实际结束的地方有多个点。
如果你的函数有多个返回值(或“res=”s),最好将它分解成几个较小的函数,每个函数都有一个退出点。
其他回答
我曾经使用过糟糕的编码标准,强迫你使用单一的退出路径,如果函数不是琐碎的,结果几乎总是非结构化的意大利面条——你最终会遇到许多中断和继续。
我想说,武断地决定不使用多个出口点是非常不明智的,因为我发现这种技术在实践中一次又一次地有用,事实上,为了清晰起见,我经常将现有的代码重构为多个出口点。我们可以这样比较这两种方法:-
string fooBar(string s, int? i) {
string ret = "";
if(!string.IsNullOrEmpty(s) && i != null) {
var res = someFunction(s, i);
bool passed = true;
foreach(var r in res) {
if(!r.Passed) {
passed = false;
break;
}
}
if(passed) {
// Rest of code...
}
}
return ret;
}
将此与允许多个出口点的代码进行比较
string fooBar(string s, int? i) {
var ret = "";
if(string.IsNullOrEmpty(s) || i == null) return null;
var res = someFunction(s, i);
foreach(var r in res) {
if(!r.Passed) return null;
}
// Rest of code...
return ret;
}
我认为后者要清楚得多。据我所知,现在对多个退出点的批评是一种相当过时的观点。
我通常的策略是在函数的末尾只有一个return语句,除非通过添加更多的return语句来大大降低代码的复杂性。事实上,我是Eiffel的粉丝,它通过没有return语句强制执行唯一的返回规则(只有一个自动创建的'result'变量来放入结果)。
当然,在某些情况下,有多个返回值的代码比没有返回值的代码更清晰。有人可能会说,如果一个函数太复杂,没有多个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++编译器中,如果你只从一个地方返回一个值,那么一个返回点可能会生成更好的代码。
但是最初的规则被误解了,被误用了。也不再相关了。
I've seen it in coding standards for C++ that were a hang-over from C, as if you don't have RAII or other automatic memory management then you have to clean up for each return, which either means cut-and-paste of the clean-up or a goto (logically the same as 'finally' in managed languages), both of which are considered bad form. If your practices are to use smart pointers and collections in C++ or another automatic memory system, then there isn't a strong reason for it, and it become all about readability, and more of a judgement call.