是“如果(...)返回...;”没有“else”算好风格?

新手上路,请多包涵

这段代码:

 if( someCondition )
    return doSomething();

return doSomethingElse();

与此代码相比:

 if( someCondition )
    return doSomething();
else
    return doSomethingElse();

本质上,它们是相同的,但是什么是最好的风格/性能/…(当然,如果答案中有任何非自以为是的部分)?还要考虑多个“if else”的情况:

 if( someCondition )
    return doSomething();
else if( someOtherCondition )
    return doSomethingDifferently();
//...
else
    return doSomethingElse();

谢谢!

原文由 rubenvb 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 354
2 个回答

当一个函数中有多个 return 语句时,这称为“提前返回”。如果您在 Google 上搜索“提前退货”,您会发现一个接一个的链接表明它很糟糕。

我说废话。

人们声称早退是不好的,有两个主要原因和一个次要原因。我将通过它们并按顺序给出我的反驳。请记住,这是我的全部意见,最终您必须自己决定。

  1. 原因:提早归还让清理变得困难。

反驳:这就是 RAII 的用途。一个设计良好的程序不会以这样一种方式分配资源,即如果执行提前离开范围,这些资源就会泄漏。而不是这样做:

 int foo()
{
  MyComplexDevice* my_device = new MyComplexDevice;
  // ...
  if( something_bad_hapened )
    return 0;
  // ...
  delete my_device;
  return 42;
}

你来做这件事:

 int foo()
{
  std::auto_ptr<MyComplexDevice> my_device(new MyComplexDevice);
  if( something_bad_hapened )
    return 0;
  // ...
  return 42;
}

并且提前返回不会导致资源泄漏。在大多数情况下,您甚至不需要使用 auto_ptr 因为您将创建数组或字符串,在这种情况下,您将使用 vectorstring 或类似的东西。

由于可能出现异常,您应该像这样设计您的代码以获得稳健性。异常是一种提前返回的形式,例如显式 return 语句,您需要准备好处理它们。您可能无法处理 foo() 中的异常,但 foo() 应泄漏。

  1. 原因:提前返回使代码更复杂。反驳:早期回报实际上使代码更简单。

职能应该有一个责任是一种普遍的理念。我同意这一点。但是人们对此太过分了,并得出结论,如果一个函数有多个返回,它必须有多个责任。 (他们通过说函数的长度不应超过 50 行或其他任意数字来扩展这一点。)我说不。仅仅因为一个函数只有一个职责,并不意味着它不需要做很多事情来履行这个职责。

以打开数据库为例。这是一项责任,但它由许多步骤组成,每个步骤都可能出错。打开连接。登录。获取一个连接对象并返回它。 3 个步骤,每个步骤都可能失败。您可以将其分解为 3 个子步骤,但不要使用这样的代码:

 int foo()
{
  DatabaseObject db = OpenDatabase(...);
}

你最终会拥有:

 int foo()
{
  Connection conn = Connect(...);
  bool login = Login(...);
  DBObj db = GetDBObj(conn);
}

因此,您实际上只是将假定的多个职责移至调用堆栈中的更高点。

  1. 原因:多个返回点不是面向对象的。反驳:这实际上只是另一种说法,“每个人都说多次退货不好,尽管我真的不知道为什么。”

换一种说法,这实际上只是试图将所有东西塞进一个物体形状的盒子里,即使它不属于那里。当然,也许连接是一个对象。但是是登录吗?登录尝试不是(IMO)对象。这是一个手术。或者算法。试图采用这种算法并将其塞进一个对象形状的盒子中是对 OOP 的无端尝试,只会导致代码更复杂、更难维护,甚至可能效率更低。

原文由 John Dibling 发布,翻译遵循 CC BY-SA 4.0 许可协议

这取决于,我更喜欢和 FredOverflow 一样

return someCondition ? doSomething() : doSomethingElse();


如果这足够了。如果不是,我想知道类似的情况 - 如果你有更长的代码 - 让我们说 30-40 行或更多,我应该把 return; 放在一个地方,这是没有必要的。例如,考虑以下情况:

 if( cond1 )
{
    if( cond2 )
    {
         // do stuff
    }
    else if( cond3 )
    {
        // ..
    }
}
else if( cond4 )
{
    // ..
}
else
{
    //..
}

我想知道的是 - 我应该在每个案例的末尾加上 return; (在 void 函数中) - 这是一种好还是坏的编码风格(因为是否有 return; 或不)。最后我决定把它说出来,因为稍后将阅读这段代码的开发人员知道这是一个最终状态,在这个函数中没有什么可以做的了。如果他/她只对这种情况感兴趣,则不要阅读其余的代码。

原文由 Kiril Kirov 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题