不使用花括号的if语句是一种不好的编程实践吗?

177

我见过像这样的代码:

if(statement)
    do this;
else
    do this;

不过,我认为这样更易读:

if(statement){
    do this;
}else{
    do this;
}

既然两种方法都可以工作,那么这只是个人偏好的问题,还是有一种方法比另一种更值得推荐?


1
在我看来这很糟糕,因为你开始依赖几乎从未完全一致的空白缩进。当读者不得不担心这些事情时,会使他们的思路偏离。 - Sridhar Sarnobat
使用它是一个好的实践 > https://blog.codecentric.de/en/2014/02/curly-braces/ - gal007
15个回答

277

第一种写法存在的问题是,如果你在if或else子句中添加第二个语句时忘记添加花括号,你的代码将以意想不到且有趣的方式崩溃。

从可维护性的角度来看,始终使用第二种形式更明智。

编辑:Ned在评论中指出了这一点,但我认为在这里也值得链接一下:https://www.imperialviolet.org/2014/02/22/applebug.html


22
你应该始终编写易于维护的代码。毕竟,我相信编译器不关心你使用哪种格式。但如果你因为一个愚蠢的花括号错误引入了一个 bug,你的同事们可能会生气。 - Esteban Araya
13
或者你可以使用一种不使用括号来表示代码块的语言... - Tor Valamo
10
@lins314159 - 不,我的意思是像 Python 这样的语言。因为在这方面我有点沙文主义。 - Tor Valamo
22
进一步证明错误可能会发生(并且确实发生了):https://www.imperialviolet.org/2014/02/22/applebug.html - Ned
9
声称SSL漏洞是支持不使用大括号的论据是不诚实的。开发人员并没有打算编写if (…) { goto L; goto L; }但是忘记了加上大括号。这只是巧合,因为“if (…) { goto L; goto L; }”仍然存在缺陷(只是没有安全后果的缺陷)。在另一个例子中,情况可能会相反,不使用大括号的代码可能会意外地安全。在第三个例子中,不使用大括号的代码最初可能没有缺陷,但是开发人员在添加大括号时可能会出现拼写错误。 - Pascal Cuoq
显示剩余14条评论

147

省略语句块的问题之一是 else 的歧义性。也就是说,受到 C 语言启发的语言忽略缩进,因此无法区分以下内容:

if(one)
    if(two)
        foo();
    else
        bar();

从这个开始:

if(one)
    if(two)
        foo();
else
    bar();

15
这是一个比顶部回答提到的问题(添加第二个声明)更为严重的问题。 - user6269864
6
的确,这个答案让我从愤世嫉俗地阅读这些答案转变为稍微担心我可能真的犯了这个错误。 - omikes
6
如果其他人和我一样想知道C语言究竟是如何解释这段代码的,经过我使用GCC进行的测试,它以第一种方式解释了这段代码。http://tpcg.io/NIYeqx - horta
6
“模棱两可”是错误的术语。在解析器处理此代码时,完全没有任何歧义:else会贪心地绑定到最近、最内层的if上。问题出现在那些编写 C 或类似语言的人身上,他们不知道这一点,没有考虑到这一点,或者还没有喝足够的咖啡 - 所以他们编写的代码可能会执行他们认为的某个操作,但语言规范却要求解析器执行完全不同的操作。是的,这是另一个坚如磐石的理由,支持始终包括大括号,即使语法将它们标记为理论上“不必要”的情况。 - underscore_d
从我所看到的(“悬挂else问题”),可读性语法是有歧义的,但是解析器要么默认选择提到的选项,要么将语法重写为不太可读,但是无歧义的形式。 - Ferazhu

45

我的通用做法是,如果它适合一行,我会这样做:

if(true) do_something();

如果有else子句,或者我想在true时执行的代码非常长,则全部使用大括号:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

归根结底,这取决于主观的风格和易读性问题。然而,在使用花括号的语言中,程序员们通常分成两派:要么总是使用它们而没有例外,要么总是使用它们但有例外。我是后者中的一员。


7
虽然写if(true){ do_something(); }很容易,但为什么要冒险让另一个程序员在以后的开发中引入严重的错误呢(可以查阅苹果公司的“goto fail” SSL代码问题)? - Craig Tullis
12
无论括号使用多少,都不能使维护者不需要动脑筋。我支持“一行内可容纳的情况下不使用括号”的想法,因为对我来说,这种情况只是一个“三元if运算符”的版本,在三元操作符的“:”部分不需要执行任何操作。那么,为什么有人要在“三元if”中引入括号呢? - Michal M
1
我完全不同意最终这是主观的,也不同意它只影响风格和可读性。作为一个曾经因为缺少块分隔符(而没有注意到它们的缺失)而浪费时间调试问题的人,因为我必须使用一种在“不必要”的情况下省略它们的编码风格,并且阅读了许多非常有争议的由此类编码风格引起的可怕错误,我认为这是一个非常客观、实际的问题。当然,如果有一种强制使用分隔符的风格,我们仍然可能会忘记它们,但至少肌肉记忆使我们更不可能忘记。 - underscore_d
只需等待格式化程序应用即可,你的一行代码就会变成两行。只需使用大括号。 - zupa
这是我们的惯例 - 要么全部写在一行,要么使用大括号。 - Daniel Williams

14

我遵循的“规则”是:

如果“if”语句是为了做某事而进行测试(例如调用函数、配置变量等),则使用大括号。

if($test)
{
    doSomething();
}
这是因为我认为您需要明确调用哪些函数以及程序的流程在什么条件下进行。让程序员完全了解在这种情况下调用了哪些函数以及设置了哪些变量,对于帮助他们准确理解您的程序正在做什么非常重要。
如果“if”语句是为了停止做某些事情(即循环或函数内的流程控制),请使用单行代码。
if($test) continue;
if($test) break;
if($test) return;

在这种情况下,对程序员来说重要的是快速发现那些异常情况,即你不希望代码运行的情况,而这些情况都在 $test 中涵盖,而不是在执行块中。


11

我正在使用我所用的IDE的代码格式化程序。这可能会有所不同,但可以在“首选项/选项”中设置。

我喜欢这个:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}

7
这是完全主观的样式问题,就我个人而言,我不喜欢仅有大括号的行出现冗余。但无妨。 - Matchu
15
我支持这种风格。大多数人从左到右阅读代码,这使我们的视线停留在屏幕的左侧。这有助于在视觉上将代码分离和提取到逻辑步骤块中。 - mloskot
6
我很喜欢这种风格,这样很容易找到相应的闭合括号。所以会占用很多空间吗?可以使用更小的字体。 - timday
4
当左右大括号在不同行时,我发现阅读代码更容易。这适用于所有情况,包括类、方法、if和while语句等等。我从来都不喜欢左大括号与其他代码在同一行。 - Svish
2
我知道这有点晚了,但是@Svish,在JavaScript中要小心return语句,突然之间花括号必须在同一行。 - ThePrimeagen
显示剩余3条评论

9

从一开始就正确使用括号应该有助于防止您需要调试这个问题:

if (statement)
     do this;
else
     do this;
     do that;

1
这似乎是被接受的理由,但(在此充当魔鬼的代言人)一个额外的语法高亮规则也可以解决这个问题,同时节省一行代码,不是吗? - Ken
3
当你按下;键时,拥有一个能够自动修正代码缩进的IDE是非常方便的 :) - Sam Harwell
一个懂C语言的程序员为什么不会注意到第二个“do that”后面没有}呢?这个缺失的大括号会立即引起我的注意。只有Python开发人员才会犯这种错误。如果在C中的代码没有新作用域的迹象,那么它通常被用来表示上一行的延续,即使上一行是else - Mecki

7

即使是简单的if语句也要使用花括号。或者重写一个简单的if语句,使用三目运算符:

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

这样看起来更加美观:

someVar= someFlag ? 'someVal1' : 'someVal2';

但是仅在您确信没有其他内容需要放入if/else块时,才使用三元运算符!


4

3
从我的经验来看,第一种形式仅有(非常)微小的优势是代码可读性更强,而第二种形式则增加了“噪音”。
但是随着现代IDE和代码自动生成(或自动完成)的出现,我强烈建议使用第二种形式,您不需要额外花费时间打大括号,而且可以避免一些最常见的错误。
有足够多的耗能错误,人们不应该为大量浪费时间开门。
编写代码时记住的最重要的规则之一是一致性。每行代码都应以相同的方式编写,无论谁编写它。严格遵循可以防止错误的发生 ;)
这与清楚明确地命名变量、方法、文件或正确缩进它们是相同的...
当我的学生接受了这个事实后,他们不再反对自己的源代码,开始将编码视为真正有趣、刺激和富有创造力的活动。他们挑战自己的头脑,而不是他们的神经!

2

这是个人喜好的问题。我个人会两种风格都使用,如果我确认不需要再添加语句,就使用第一种风格,否则我使用第二种风格。由于第一种风格无法再添加语句,我听说有些人建议不要使用它。但是,第二种方法会增加一行代码,如果你(或你的项目)使用这种编码风格,第一种方法在简单的if语句中非常受欢迎:

if(statement)
{
    do this;
}
else
{
    do this;
}

然而,我认为解决这个问题的最佳方法是使用Python。由于基于空格的块结构,您不会有两种不同的创建if语句的方法:只有一种:

if statement:
    do this
else:
    do this

虽然这种写法有“问题”,即您不能使用大括号,但您可以获得更多的语句并且不会比第一种写法占用更多的行数。

我个人认为Python处理if-else语句的方式非常丑陋,但再说一遍,我还不是Python程序员(尚未)。 - helpermethod

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