此代码:
if( someCondition )
return doSomething();
return doSomethingElse();
与此代码对比:
if( someCondition )
return doSomething();
else
return doSomethingElse();
从本质上讲,它们是相同的,但什么是最好的风格/表现/ ...(当然,如果答案中有任何非自以为是的部分)?还要考虑具有多个“if else's”的情况:
if( someCondition )
return doSomething();
else if( someOtherCondition )
return doSomethingDifferently();
//...
else
return doSomethingElse();
谢谢!
答案 0 :(得分:43)
如果函数中有多个return语句,则称为“提前返回”。如果您为“提前退货”执行了Google search,则会在链接后发现链接显示该链接很糟糕。
我说废话。
有两个主要原因和一个次要原因是人们声称早期回归是坏事。我将通过它们并按顺序给出我的反驳。请记住这是我的全部意见,最终你必须自己决定。
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
,因为您将创建数组或字符串,例如,您将使用vector
,string
或类似的东西。
由于存在异常的可能性,您应该设计这样的代码以保持稳健性。异常是一种早期返回的形式,如明确的return
语句,您需要准备好处理它们。您可能无法在foo()
中处理异常,但foo()
无论如何都不会泄露。
2)原因:早期返回使代码更复杂。 反驳:早期的回报实际上使代码更简单。
一个共同的理念是,职能应该有一个责任。我同意这一点。但人们认为这太过分了,并得出结论,如果一个函数有多个回报,它必须有多个责任。 (他们通过说函数永远不会超过50行,或者其他任意数字来扩展它。)我说不。仅仅因为一个函数只有一个责任,并不意味着它没有太多的事情可以实现这个责任。
以打开数据库为例。这是一个责任,但它由许多步骤组成,每个步骤都可能出错。打开连接。登录。获取连接对象&amp;把它返还。 3个步骤,每个步骤都可能失败。您可以将其分解为3个子步骤,但之后不要使用这样的代码:
int foo()
{
DatabaseObject db = OpenDatabase(...);
}
你最终会得到:
int foo()
{
Connection conn = Connect(...);
bool login = Login(...);
DBObj db = GetDBObj(conn);
}
所以你真的只是把假定的多个职责移到了调用堆栈的更高点。
3)原因:多个返回点不是面向对象的。 反驳:这实际上只是另一种说法,“每个人都说多重回报都很糟糕,但我真的不知道为什么。”
采取另一种方式,这实际上只是尝试将所有东西塞进一个物体形状的盒子中,即使它不属于那里。当然,也许连接是一个对象。但是登录了吗?登录尝试不是(IMO)对象。这是一个操作。或算法。试图采用这种算法并将其塞入一个对象形状的盒子是对OOP的无偿尝试,并且只会导致代码更复杂,更难维护,甚至可能效率更低。
答案 1 :(得分:8)
功能应该尽快返回。这节省了不必要的语句中的语义开销。尽快返回的函数提供最高的清晰度和最干净,最易维护的源代码。
当你必须手动编写以释放你分配的每一个资源时,SESE风格的代码很好,并且记住在几个不同的地方释放它们都是浪费。然而,现在我们有了RAII,它肯定是多余的。
答案 2 :(得分:3)
这纯粹是个人偏好或编码标准的问题。就个人而言,我更喜欢第三种变体:
return someCondition ? doSomething() : doSomethingElse();
答案 3 :(得分:3)
这取决于,我更喜欢FredOverflow
return someCondition ? doSomething() : doSomethingElse();
如果这足够了。如果不是,我想知道类似的情况 - 如果你有更长的代码 - 让我说30-40行或更多,我应该把return;
放在一个地方,这是没有必要的。例如,请考虑以下情况:
if( cond1 )
{
if( cond2 )
{
// do stuff
}
else if( cond3 )
{
// ..
}
}
else if( cond4 )
{
// ..
}
else
{
//..
}
我想知道的是 - 我应该在每个案例结尾处放置return;
(在void函数中) - 这是一种好的还是坏的编码风格(因为return;
是无关紧要的或不)。最后我决定把它,因为开发人员稍后会读到这段代码,知道这是一个最终状态,并且在这个函数中没有什么可以做的了。如果他/她仅在这种情况下感兴趣,不要阅读其余的代码。
答案 4 :(得分:-1)
取决于。
如果你遵循早期回报的约定来处理错误案例那么这很好,如果你只是在做任意事情那么它就是坏事。
所呈现的代码最严重的问题是你没有使用花括号。这意味着不太了解清晰度是什么。如果不是因为我只是以“目标明确”来回答您的主要问题,但首先您需要了解清晰度。作为这条道路的第一步,开始使用花括号。尝试让其他人可以阅读您的代码,以便其他人可以一目了然(或者自己月/年后)。
干杯&amp;第h。,