在每个if条件中都需要写else部分吗?

19
我的问题可能会被关闭,但我很好奇在编程中是否总是需要在每个“if”语句中添加一个“else”部分。一位资深程序员告诉我:“你应该在每个‘if’语句中都有一个‘else’部分。”然而,如果没有理由包含一个“else”部分,我们应该怎么办呢?我认为这可能会引发一场有趣的讨论。

2
我尽量不对同事指手画脚,这样往往会让事情变得混乱。只有在有意义的情况下才使用else语句。 - kbrimington
1
如果你总是听取同事的意见,你会养成他们的坏习惯。没有必要说“否则”,你要亲自学习。 - Laramie
2
我认为你的高级程序员实际上是这样说的:“你应该在每个if条件中考虑else部分”。由于缺少else块,我见过太多的代码出现了掉落情况。 - Gilbert Le Blanc
似乎这里有一个更好的答案:https://dev59.com/N1sW5IYBdhLWcg3wX2Vz - wonko realtime
Kubernetes 称之为“航天飞机风格”,用于帮助确保正确性 - 值得一读:https://github.com/kubernetes/kubernetes/blob/ec2e767e59395376fa191d7c56a74f53936b7653/pkg/controller/volume/persistentvolume/pv_controller.go - David Ljung Madison Stellar
12个回答

18

那是一个可怕的想法。你最终会得到这种形式的代码:

if (something) {
    doSomething();
} else {
}

我无法理解任何人怎么可能会认为这比根本不用else更具可读性和可维护性。这听起来像是由一些手头过于闲余的人制定的规则。尽快让他们被解雇,或者至少静静地离开。


1
"一种选择是编写else子句 - 如果必要,使用空语句来显示已考虑else情况。编写空的else子句仅为了表明已考虑该情况可能有些过度,但至少要考虑else情况。当您有一个没有else的if测试时,除非原因很明显,否则请使用注释来解释为什么不需要else子句。" - 《代码大全》我感到矛盾,你怎么看? - doubleOrt
我认为,就像那本书中引用的很多东西一样,它需要在上下文中:前面的句子是:“如果你认为你需要一个简单的if语句,考虑是否实际上你不需要一个if-then-else语句。”我写的每一行代码都是经过深思熟虑的结果:在这种情况下,被拒绝了,因为一个合格的程序员会知道缺少else子句意味着不应该采取任何行动。我不会阅读一个函数并想象从未放置在其末尾的七行代码,这正是您应该对缺少else的态度 :-) - paxdiablo
这本好书的问题在于它有时会提出非常明显/初学者的观点。例如,在前一页中,它说“你应该避免使用'if-then-else'语句,其中'if'块在其主体中没有语句,而是取反测试条件”(我是在转述)。 - doubleOrt
虽然我并不是在抱怨,但我宁愿选择一本明显陈述的书籍,而非含有谜一般的晦涩之作。因为作者所设立的明智/不明显的界限(这可能根本无法实现,因为每个人都有不同的知识和经验)放错了位置。 - doubleOrt

8
不,大多数语言都不需要这样做(你没有说明,有可能某些语言是强制要求的)。以下是一个例子,我肯定不会这样做:
public void DoSomething(string text)
{
    if (text == null)
    {
        throw new ArgumentNullException("text");
    }
    // Do stuff
}

现在你可以将方法的主要工作放在这里的“else”子句中,但这样做会增加不必要的嵌套。添加更多条件,整个代码就会变得难以阅读。
在我看来,“提前退出”的模式相当常见,适用于返回值和异常。我知道有些人支持从方法中返回单个点,但在我使用的语言(Java、C#)中,这通常会导致代码可读性更差和更深的嵌套。
现在,有一种情况需要更多讨论,那就是两个分支都是终止分支,但它们都不是有效的快捷方式:
public int DoSomething()
{
    // Do some work
    if (conditionBasedOnPreviousWork)
    {
        log.Info("Condition met; returning discount");
        return discount;
    }
    else
    {
        log.Info("Condition not met; returning original price");
        return originalPrice;
    }
}

(请注意,我故意让两个分支做更多的工作,而不仅仅是返回 - 否则条件语句就是适当的。)这种写法没有“否则”会更易读吗?这实际上是个人选择的问题,我不会声称我总是一致的。将两个分支同样缩进使它们具有相等的重要性 - 可能鼓励通过反转条件来重新设计...如果我们直接跳到“返回原始价格”,将其放入if块中并将折扣案例移出if块中的重构一开始可能不太正确。

5
在像Java和C这样的命令式语言中,if-else是一种语句,并不返回任何值。因此,您可以只写if部分并继续进行。我认为这是比在每个if后面添加空的else更好的做法。
然而,在Haskell和Clojure等函数式语言中,if是一个表达式,必须返回一个值。因此,必须加上一个else。但是还有一些情况下可能不需要else部分。对于这种情况,Clojure有一个when宏,它将if-else包装起来,在else部分返回nil并避免编写它。
(when (met? somecondition)
  (dosomething))

1
+1 是唯一提到 if-else 表达式的答案,非常棒。 - missingfaktor

4

1
我知道我来晚了,但我经过深思熟虑,想分享我的结果。
在关键代码中,每个分支都必须被考虑到。写else并不是必要的,但要留下标记说明为什么else不是必要的。这将有助于审核人员。请看以下示例:
//negatives should be fixed
if(a < 0) {
    a+=m;
}
//else value is positive

1

从语义角度来看,我无法想到任何一个情况下每个if都没有隐含的else。

如果在我到达墙之前汽车没有停止,我会撞上去,否则我不会撞上去。

撇开语义不谈:

这个问题的答案取决于环境和错误的结果。

商业代码?按照你的编码标准去做。
在我看来,尽管最初似乎需要付出过多的努力,但详细说明它将在10年后重新访问该代码时变得非常有价值。但是,如果你错过了重要的“反条件”,这当然不会是世界末日。

然而:安全、生命关键代码?那就是另外一回事。

在这种情况下,你想要做两件事。
首先:与其测试故障,不如证明没有故障。这需要对进入任何模块持悲观态度。你假设一切都是错误的,直到你证明它是正确的。
其次:在生命关键时刻:你永远不想伤害病人。

bool everyThingIsSafe = true;
if(darnThereIsAProblem())
{
   reportToUserEndOfWorld();
}
return everyThingIsSafe;

糟糕,我忘记将everyThingIsSafe设置为false了。
调用此片段的例程现在被欺骗了。如果我将evertThingIsSafe初始化为false - 我总是安全的,但现在我需要else子句来指示没有错误发生。
是的,我可以将其更改为正测试,但然后我需要else来处理故障。
是的,我可以将everyThingIsSafe()分配为检查的立即返回值。然后测试标志以报告问题。一个隐含的else,为什么不明确呢?
严格来说,这个隐含的else是合理的。
对于FDA/安全审计员来说,也许不是。
如果它是显式的,可以指向测试、它的else和我清楚地处理了两种情况。

我已经为医疗设备编码25年了。在这种情况下,您想要else,您想要默认情况,并且它们永远不为空。您想确切地知道会发生什么,或者尽可能接近。因为忽视一个条件可能会导致某人死亡。

查找Therac-25。8人重伤。3人死亡。


1

不需要为if语句编写else部分。

事实上,大多数开发人员更喜欢和建议避免使用else块。

也就是说

不要写成

if (number >= 18) {
    let allow_user = true;
} else {
    let allow_user = false;
}

Most of the developers prefer:

let allow_user = false;
if (number >= 18) {
    let allow_user = true;
}

0
def in_num(num):
    if num % 3 == 0:
        print("fizz")
    if num % 5 == 0:
        print("buzz")
    if (num % 3 !=0) and (num % 5 !=0):
        print(num)

在这段代码中,else语句是不必要的。


这是一个Fizz Buzz问题,不需要其他东西。 - Sutoshi Nukamoto

0

不需要,但我个人选择始终包含封装大括号以避免错误

if (someCondition)
    bar();
    notbar();  //won't be run conditionally, though it looks like it might

foo();

我会写

 if (someCondition){
        bar();
        notbar();  //will be run
 }
 foo();

2
我的规则是,单行的if语句不需要使用大括号,但如果语句的内容跨越多行,则需要使用大括号。 - Thom Smith

0

不,你不必这样做。

而且,我认为这对于可读性来说并不是一个好主意,因为你会有很多空的else块,这看起来并不美观。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接