例如,当我在我的代码上运行ReSharper时:

    if (some condition)
    {
        Some code...            
    }

ReSharper给了我上面的警告(反转“if”语句以减少嵌套),并建议以下更正:

   if (!some condition) return;
   Some code...

我想知道为什么这样更好。我一直认为在方法中间使用“return”是有问题的,有点像“goto”。


当前回答

避免多个退出点可以提高性能。我对c#不太确定,但在c++中,命名返回值优化(复制省略,ISO c++ '03 12.8/15)依赖于有一个单一的出口点。这种优化避免了复制构造返回值(在您的特定示例中,这无关紧要)。在紧密循环中,这可能会大大提高性能,因为每次调用函数时都保存了一个构造函数和一个析构函数。

但是在99%的情况下,节省额外的构造函数和析构函数调用并不值得损失嵌套的可读性,如果块引入(正如其他人所指出的)。

其他回答

在我看来,如果你只是返回void(或一些你永远不会检查的无用的返回代码),那么早期返回是很好的,它可能会提高可读性,因为你避免了嵌套,同时你显式地表明你的函数已经完成。

如果你实际上返回一个returnValue,嵌套通常是一个更好的方式,因为你只在一个地方返回你的returnValue(在末尾),它可能会使你的代码在很多情况下更易于维护。

保护子句或先决条件(正如您可能看到的那样)检查是否满足某个条件,然后中断程序的流程。它们适用于只对if语句的一个结果感兴趣的地方。所以不要说:

if (something) {
    // a lot of indented code
}

反转条件,如果反转条件满足,则中断

if (!something) return false; // or another value to show your other code the function did not execute

// all the code from before, save a lot of tabs

返回远没有去到那么脏。它允许您传递一个值来显示函数无法运行的其余代码。

你将看到在嵌套条件下应用这个的最佳示例:

if (something) {
    do-something();
    if (something-else) {
        do-another-thing();
    } else {
        do-something-else();
    }
}

vs:

if (!something) return;
do-something();

if (!something-else) return do-something-else();
do-another-thing();

你会发现很少有人认为第一种说法更清晰,当然,这完全是主观的。有些程序员喜欢通过缩进来知道某些东西在什么条件下运行,而我更愿意保持方法流是线性的。

我不是说precons会改变你的生活或让你上床,但你可能会发现你的代码更容易阅读。

我想补充的是,这些倒置的if是有名称的-保护条款。我一有机会就用它。

我讨厌阅读一开始只有两屏代码的代码。只要求if的倒数,然后返回。这样就没人会浪费时间刷屏幕了。

http://c2.com/cgi/wiki?GuardClause

表演分为两部分。在软件处于生产状态时,您需要性能,但在开发和调试时也需要性能。开发人员最不想做的事情就是“等待”一些微不足道的事情。最后,在启用优化的情况下编译该代码将生成类似的代码。所以知道这些在两种情况下都有好处的小技巧是很好的。

问题中的情况很清楚,ReSharper是正确的。不是嵌套if语句,也不是在代码中创建新的作用域,而是在方法的开头设置一个明确的规则。它增加了可读性,更容易维护,并减少了人们必须筛选的规则数量。

方法中间的返回并不一定是坏的。如果能使代码的意图更清晰,那么立即返回可能会更好。例如:

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

在这种情况下,如果_isDead为真,我们可以立即退出该方法。也许这样结构会更好:

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

    return normalPayAmount();
};   

我从重构目录中挑选了这段代码。这种特殊的重构被称为:用保护子句替换嵌套条件句。