为什么在"if x then return"之后很少使用"else"?

Tod*_*wen 60 java if-statement coding-style function-exit

这个方法:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }
    else {
        return s.contains(":)");
    }
}
Run Code Online (Sandbox Code Playgroud)

可以等同地写成:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }

    return s.contains(":)");
}
Run Code Online (Sandbox Code Playgroud)

根据我的经验,第二种形式更常见,特别是在更复杂的方法中(可能有几个这样的退出点),"throw"和"return"也是如此.然而,第一种形式可以说使代码的条件结构更加明确.有什么理由比较喜欢一个吗?

(相关:一个函数应该只有一个return语句吗?)

Del*_*ani 87

else这种情况下是多余的,以及对功能的主要代码创建不必要的额外缩进.

  • 确切地说,if子句之后的任何东西基本上都在else语句中,因为到达那里的唯一方法是绕过if,条件为false,因为如果条件为真,则方法返回,之后没有别的if被执行了. (3认同)

Rei*_*ica 70

根据我的经验,这取决于代码.如果我'守护'某事,我会做:

if (inputVar.isBad()) {
    return;
}

doThings();
Run Code Online (Sandbox Code Playgroud)

重点很明确:如果该语句为false,我不希望该函数继续.

另一方面,有一些函数有多个选项,在这种情况下我会这样写:

if (inputVar == thingOne) {
    doFirstThing();
} else if (inputVar == secondThing) {
    doSecondThing();
} else {
    doThirdThing();
}
Run Code Online (Sandbox Code Playgroud)

即使它可以写成:

if (inputVar == thingOne) {
    doFirstThing();
    return;
}
if (inputVar == thingTwo) {
    doSecondThing();
    return;
}
doThingThree();
return;
Run Code Online (Sandbox Code Playgroud)

它真正归结为哪种方式最清楚地显示代码正在做什么(不一定代码的哪一部分最短或压痕最少).

  • 我从所有这些中得到的结论是:函数的开始或结束附近的返回语句可能很好,但是复杂函数中途的返回语句是代码气味(即考虑重构以减少退出点). (6认同)

Eug*_*ota 32

这是一种名为Guard Clause的模式.我们的想法是预先进行所有检查,以减少嵌套条件,从而提高可读性.

从链接:

double getPayAmount() {
    double result;
    if (_isDead) {
        result = deadAmount();
    } else {
        if (_isSeparated) {
            result = separatedAmount();
        } else {
            if (_isRetired) {
                result = retiredAmount();
            } else {
                result = normalPayAmount();
            }
        }
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

使用Guard子句,您将看到以下结果:

double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired) return retiredAmount();

    return normalPayAmount();
};
Run Code Online (Sandbox Code Playgroud)

  • @chpwn,模式只不过是一些社区共享的词汇,这些词汇已经存在于该领域.我曾经把这个称为"早早出去",但是有一些能传达这个概念的词是很好的,所以知道它的人会得到一秒钟. (5认同)
  • 这个例子正是我们不一定需要所有事情都有一个出口点的原因。 (2认同)
  • @bitschnau,从性能的角度来看,运行探查器并优化只重要的代码是个好主意. (2认同)
  • 只是在这里推测,但是您的“来自链接”的代码是一个糟糕的例子。该代码应该是`if(_isDead)... else if(_isSeparated)... else if`(等等),以减少所有缩进。嵌套所有这些if / eles绝对是可怕的,但是有人真的很好地检查了他们的代码以问这个问题,应该具有将“ else {if / else}”组合成“ else if”的感觉。 (2认同)

amp*_*ine 8

你会看到这一切:

if (condition) {
    return var;
}
// by nature, when execution reaches this point, condition can only be false,
// therefore, the else is unnecessary
return other_var;
Run Code Online (Sandbox Code Playgroud)

大多数情况下,在这种情况下添加else子句不仅是不必要的,而且很多时候,它会被编译器优化掉.

想想计算机如何看待这个代码(就机器代码而言,为了演示目的简化为伪代码):

0x00: test [condition]
0x01: if result of test was not true, goto [0x04]
0x02: push [var] onto stack
0x03: goto [0x05]
0x04: push [other_var] onto stack
0x05: return from subroutine
Run Code Online (Sandbox Code Playgroud)

代码(再次,这是一个伪代码而不是汇编)对if/then/else条件的行为完全相同.

很多人认为,对于函数来说,有多个可能的出口点是不好的和/或混乱的做法,因为程序员必须通过他的代码思考每条可能的路径.另一种做法如下:

return (condition) ? var : other_var;
Run Code Online (Sandbox Code Playgroud)

这简化了代码,并且不会创建任何新的退出点.


Cha*_*ion 7

我更喜欢这样写:

boolean containsSmiley(String s) {
    return s != null && s.contains(":)");
}
Run Code Online (Sandbox Code Playgroud)

  • +1 因为这是一个谓词并且大多数谓词都是单行的......但它并没有真正回答这个问题 (2认同)