关于缩进:在函数开头使用return来避免做不必要的工作是不好的风格?

Is it bad style to use return at the beginning of a function to avoid doing unnecessary work?

假设我们有一个函数foo()和一个bool条。如果bar为false,foo所做的工作将毫无用处。写foo()最合适的方法是什么?

1
2
3
4
5
foo() {
  if(!bar)
    return;
  doWork();
}

1
2
3
4
foo() {
  if(bar)
    doWork();
}

选项1的美学优势是dowork()(即函数的其余部分)不缩进,但缺点是,如果不查看早期返回语句,则可以假定每次调用foo()时都调用dowork()。

一般来说,用样式1编码是不好的做法,还是应该是个人偏好?


样式1对于保护声明非常有用。这样地:

1
2
3
4
5
6
void work() {
  if (!something)
     return;

  //do the job
}

否则,我会说这取决于情况。如果if与以下逻辑紧密相连,我将使用style 2,否则我将使用style 1。总结:总是使用能使代码更清晰和可读的代码。


有些人总是会对你说"有一个单一的出口点"的咒语。

有时,如果您需要对每个出口点执行特定的操作,这很有意义。我想说,在这种情况下,保持清醒是至关重要的。

现在,如果您没有这个需求,我个人认为,只要您尽快退出并保持代码的识别级别较低,就没有问题。

我见过有人用do包装整个代码……}while(0);block只保留单个出口点规则,使用break而不是return。这让我发疯。但在某些情况下,它可能是一个有用的设备。

总的来说,使用常识,在你的具体问题上使用更有意义的东西。


我的2分价值:如果你保持你的函数很小,多次返回不是一个真正的问题。在大型函数(可能需要重构,但有时不重构)中,多个返回语句(尤其是嵌套控制结构中的)开始表现得像goto,这使得函数更难解释。


这是一种个人偏好,非常主观——你很可能会看到很多关于这方面的意见。嗯,这两种款式都没有问题。每个都以合理的方式显示控制流,选项1实际上在检查某些功能参数等方面非常有用。


对函数进行编码的正确方法是有一个入口点和一个出口点。这样做可以更容易地维护和调试应用程序。根据您的示例,您应该使用所呈现的第二种样式编写代码:

1
2
3
4
foo() {
  if(bar)
    doWork();
}