是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?

或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?


当前回答

函数中return语句越多,该方法的复杂性就越高。如果您发现自己想知道是否有太多的return语句,那么您可能需要问问自己,该函数中是否有太多的代码行。

但是,不是,一个/多个返回语句并没有错。在某些语言中,这是一种比其他语言(C)更好的实践(c++)。

其他回答

如果你最终得到了很多返回值,那么你的代码可能有问题。否则,我同意有时能够从子例程的多个位置返回是很好的,特别是当它使代码更干净的时候。

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]
}

注意,这只是一个简单的例子

函数中return语句越多,该方法的复杂性就越高。如果您发现自己想知道是否有太多的return语句,那么您可能需要问问自己,该函数中是否有太多的代码行。

但是,不是,一个/多个返回语句并没有错。在某些语言中,这是一种比其他语言(C)更好的实践(c++)。

是否有充分的理由说明在函数中只有一个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的指导方针显然也提倡单次退出。

需要澄清的是,我并不是说拥有多个回报总是错误的。但如果有其他等价的解决方案,有很多很好的理由选择单一回报的方案。

拥有多个出口点本质上与使用GOTO是一样的。这是不是件坏事取决于你对迅猛龙的看法。

如果管理得当,多次退出是件好事

第一步是明确退出的原因。我的通常是这样的: 1. 不需要执行函数 2. 发现错误 3.提前完成 4. 正常完成 我想你可以把“1”归为一类。不需要执行函数“into”3。提前完成”(如果你愿意的话,可以说是非常提前完成)。

第二步是让函数外部的人知道退出的原因。伪代码看起来像这样:

function foo (input, output, exit_status)

  exit_status == UNDEFINED
  if (check_the_need_to_execute == false) then
    exit_status = NO_NEED_TO_EXECUTE  // reason #1 
    exit

  useful_work

  if (error_is_found == true) then
    exit_status = ERROR               // reason #2
    exit
  if (need_to_go_further == false) then
    exit_status = EARLY_COMPLETION    // reason #3
    exit

  more_work

  if (error_is_found == true) then
    exit_status = ERROR
  else
    exit_status = NORMAL_COMPLETION   // reason #4

end function

显然,如果将上图中的一大块工作移到一个单独的函数中是有益的,那么您应该这样做。

如果您愿意,您可以使用更具体的退出状态,例如,使用几个错误代码和早期完成代码来精确定位退出的原因(甚至位置)。

即使您强制这个函数只有一个出口,我认为您仍然需要指定出口状态。调用者需要知道是否可以使用输出,这有助于维护。