在单行if或循环中使用大括号(即{})的目的是什么?

我在读c++老师的课堂笔记,他是这样写的:

  1. 使用缩进// OK
  2. 永远不要依赖运算符优先级-总是使用括号// OK
  3. 总是使用{}块-即使是单行// 不可以,为什么??
  4. Const对象在比较的左边// OK
  5. 对>= 0的变量使用unsigned,这是个不错的技巧
  6. 删除后将指针设置为NULL -双重删除保护//不错
第三个技巧我不清楚:放一行进去能得到什么 { ... }吗?< / p >

例如,下面这段奇怪的代码:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}

将其替换为:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;

使用第一个版本的好处是什么?

47648 次浏览

让我们尝试在增加j时也修改i:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
i++;

噢,不!来自Python,这看起来不错,但实际上不是,因为它相当于:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
i++;

当然,这是一个愚蠢的错误,但即使是有经验的程序员也会犯这个错误。

另一个很好的理由是在ta.speot。的回答是中指出的。

我能想到的第三个是嵌套的if:

if (cond1)
if (cond2)
doSomething();

现在,假设你现在想在cond1不满足时doSomethingElse()(新特性)。所以:

if (cond1)
if (cond2)
doSomething();
else
doSomethingElse();

这显然是错误的,因为else与内部的if相关联。


编辑:既然这引起了一些关注,我将澄清我的观点。我想回答的问题是

使用第一个版本的好处是什么?

我已经描述过了。有一些好处。但是,在我看来,“总是”的规则并不总是适用。所以我并不完全支持

总是使用{}块-即使是单行//不可以,为什么??

我并不是说总是使用{}块。如果这是一个足够简单的条件&;行为,不。如果你怀疑有人可能稍后会进来&更改代码以添加功能。

它更直观,更容易理解。它使意图明确。

并且它确保当新用户在添加新代码语句时可能不知不觉地错过{}时,代码不会中断。

如果你不使用{},很容易意外地用注释改变控制流。例如:

if (condition)
do_something();
else
do_something_else();


must_always_do_this();

如果你用一行注释注释掉do_something_else(),你会得到这样的结果:

if (condition)
do_something();
else
//do_something_else();


must_always_do_this();

它会编译,但并不总是调用must_always_do_this()

我们在代码库中遇到了这个问题,有人在发布之前很快地禁用了一些功能。幸运的是,我们在代码审查中发现了它。

它通过清楚地定义循环和条件块的范围,使您的代码更具可读性。它还可以避免你意外出错。

如果你是一个编译器,这没有任何区别。两者是一样的。

但是对于程序员来说,第一个更清晰,更容易阅读,更不容易出错。

wrt 6:它更安全,因为删除空指针是一个无操作。因此,如果您碰巧两次经过这条路径,您不会因为释放空闲内存或已分配给其他内存而导致内存损坏。

这是静态文件作用域对象和单例对象的主要问题,它们没有非常明确的生命周期,并且已知它们在被销毁后会被重新创建。

在大多数情况下,您可以通过使用auto_ptrs来避免这种需要

我对这位讲师的能力表示怀疑。考虑到他 点:< / p >
  1. 好吧
  2. 真的有人会写(或想读)(b*b) - ((4*a)*c)吗? 一些优先级是明显的(或者应该是),以及额外的括号 只会增加困惑。(另一方面,你应该使用 括号在不太明显的情况下,即使你知道它们不是 需要的。) <李>。有两种广泛使用的格式约定 条件语句和循环语句:
    if ( cond ) {
    code;
    }
    
    和:
    if ( cond )
    {
    code;
    }
    
    首先,我同意他的观点。{开头不是那么可见, 所以最好假设它一直在那里。然而,在第二种情况下,我 (和我一起工作过的大多数人)对省略没有问题 用于单个语句的大括号。(当然,前提是 缩进是系统的,您可以始终使用这种样式。 (很多优秀的程序员,在编写可读性很强的代码时,省略了这些代码 即使是用第一种方式格式化,也要使用大括号。) <李> 没有。像if ( NULL == ptr )这样的东西丑陋到足以妨碍 可读性。直观地写出比较。(在很多情况下 结果是右边的常数。)他的4是个坏建议;任何东西 这使得代码不自然,可读性更差。 <李> 没有。除int之外的任何值都保留给特殊情况。来 有经验的C和c++程序员,使用unsigned信号位 操作符。c++没有真正的基本类型(或任何其他类型) 有效子量程类型);unsigned不适用于数值, 因为晋升规则。数值 算术运算是有意义的,就像序列号一样 大概是unsigned。然而,我会反对,因为它 发送错误的信息:按位操作也没有意义。 基本规则是整型为int,除非有 使用其他类型的重要原因。 <李> 没有。系统性地这么做是误导,实际上也不是 保护自己免受任何伤害。在严格的OO代码中,delete this;通常是 最常见的情况(并且你不能将this设置为NULL),以及 否则,大多数delete都在析构函数中,因此不能访问 反正以后会有指针。将它设置为NULL并不会做任何事情 关于其他浮动的指针。设置指针 系统地NULL会给人一种虚假的安全感,但事实并非如此 真的给你买任何东西。
查看任何典型引用中的代码。Stroustrup违反

.

.

. 我建议你另找一个讲师。一个真正知道什么的人 他在谈论。

我正在处理的代码库被那些病态地厌恶大括号的人分散在代码中,对于后来的人来说,它确实可以对可维护性产生影响。

我遇到的最常见的问题是:

if (really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
this_looks_like_a_then-statement_but_isn't;

所以当我出现并希望添加一个then语句时,如果我不小心,我很容易以这样的方式结束:

if (really incredibly stupidly massively long statement that exceeds the width of the editor) do_foo;
{
this_looks_like_a_then-statement_but_isn't;
i_want_this_to_be_a_then-statement_but_it's_not;
}

考虑到添加大括号需要大约1秒钟,并且可以为你节省至少几分钟的调试时间,为什么你要使用减少歧义选项呢?在我看来这是虚假的节约。

为了补充之前回答中非常明智的建议,我在重构一些代码时遇到的一个例子是:我正在修改一个非常大的代码库,从一个API切换到另一个API。第一个API调用设置Company Id,如下:

setCompIds( const std::string& compId, const std::string& compSubId );

而替换需要两次调用:

setCompId( const std::string& compId );
setCompSubId( const std::string& compSubId );

我开始使用正则表达式来改变这种情况,这非常成功。我们还通过astyle传递代码,这确实使它更易于阅读。然后,在审查过程中,我发现在某些条件下,它正在改变:

if ( condition )
setCompIds( compId, compSubId );

:

if ( condition )
setCompId( compId );
setCompSubId( compSubId );

这显然不是我们所需要的。我不得不回到一开始,再次将替换处理为完全在一个块内,然后手动修改任何最终看起来愚蠢的东西(至少它不会是不正确的)。

我注意到astyle现在有选项--add-brackets,它允许你在没有括号的地方加括号,如果你发现自己处于和我一样的位置,我强烈建议你这样做。

所有其他答案都捍卫了讲师的规则3。

让我说我同意你:这个规则是多余的,我不建议它。的确,如果你总是添加花括号,它从理论上讲可以防止错误。另一方面,我在现实生活中从未遇到过这个问题:与其他答案所暗示的相反,我从未忘记在必要时添加花括号。如果使用适当的缩进,一旦多个语句缩进,就需要立即添加花括号。

答案由组件10实际上突出了唯一可能导致错误的情况。但另一方面,通过正则表达式替换代码总是需要非常小心。

现在让我们看看奖章的另一面:总是使用大括号是否存在缺点 ?其他答案完全忽略了这一点。但是有一个缺点:它占用了大量的垂直屏幕空间,这反过来会使你的代码不可读,因为这意味着你必须滚动更多的必要。

考虑一个函数在开头有很多保护子句(是的,下面是糟糕的c++代码,但在其他语言中,这将是相当常见的情况):

void some_method(obj* a, obj* b)
{
if (a == nullptr)
{
throw null_ptr_error("a");
}
if (b == nullptr)
{
throw null_ptr_error("b");
}
if (a == b)
{
throw logic_error("Cannot do method on identical objects");
}
if (not a->precondition_met())
{
throw logic_error("Precondition for a not met");
}


a->do_something_with(b);
}

这是可怕的代码,我强烈认为下面的代码可读性更强:

void some_method(obj* a, obj* b)
{
if (a == nullptr)
throw null_ptr_error("a");
if (b == nullptr)
throw null_ptr_error("b");
if (a == b)
throw logic_error("Cannot do method on identical objects");
if (not a->precondition_met())
throw logic_error("Precondition for a not met");


a->do_something_with(b);
}

类似地,短嵌套循环可以从省略花括号中获益:

matrix operator +(matrix const& a, matrix const& b) {
matrix c(a.w(), a.h());


for (auto i = 0; i < a.w(); ++i)
for (auto j = 0; j < a.h(); ++j)
c(i, j) = a(i, j) + b(i, j);


return c;
}

比较:

matrix operator +(matrix const& a, matrix const& b) {
matrix c(a.w(), a.h());


for (auto i = 0; i < a.w(); ++i)
{
for (auto j = 0; j < a.h(); ++j)
{
c(i, j) = a(i, j) + b(i, j);
}
}


return c;
}

第一个代码很简洁;第二个代码很臃肿。

是的,这可以通过将开大括号放在前一行来缓解在某种程度上。所以:如果你坚持使用大括号,至少要把左大括号放在前一行。

简而言之:不要编写占用屏幕空间的不必要代码。


在最初写答案的时间里,我基本上接受了流行的代码风格,使用大括号,除非我能把整个语句放在前一行。我仍然认为不使用冗余大括号通常更具可读性,并且我已经还从来没有遇到了由此引起的错误。

我的2 c:

使用缩进

很明显

永远不要依赖运算符优先级——总是使用括号

我不会使用“从不”和“总是”这样的词,但总的来说,我认为这条规则是有用的。在某些语言(Lisp, Smalltalk)中,这不是问题。

总是使用{}块-即使是单行

我从来没有这样做过,也从来没有遇到过任何问题,但我可以看到它对学生有什么好处,特别是如果他们以前学过Python的话。

Const对象在比较的左边

尤达条件?不,请。它损害了可读性。在编译代码时使用最大警告级别即可。

对于>= 0的变量使用unsigned

好的。有趣的是,我听到斯特劳斯特鲁普不同意。

删除后将指针设置为NULL -双重删除保护

坏的建议!永远不要使用指向已删除或不存在的对象的指针。

我喜欢卢钦接受的答案。事实上,我经过艰苦的学习才知道他是对的,所以我总是使用大括号,即使是单行块。然而,就我个人而言,我在编写过滤器时做了一个例外,就像您在示例中所做的那样。这样的:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}

在我看来很混乱。它将'for'循环和'if'语句分离为单独的操作,而实际上你的目的是一个操作:计算所有能被2整除的整数。在更有表现力的语言中,可以这样写:

j = [1..100].filter(_%2 == 0).Count

在缺少闭包的语言中,过滤器不能在单个语句中表示,而必须是循环后跟如果语句。然而,这仍然是程序员心中的一个动作,我相信这应该反映在代码中,如下所示:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
{
j++;
}

我在所有地方都使用{},除了一些明显的情况。单行是其中一种情况:

if(condition) return; // OK


if(condition) //
return;    // and this is not a one-liner

当你在返回之前添加一些方法时,它可能会伤害你。缩进表示当条件满足时执行return,但它总是返回。

c#中using语句的其他例子

using (D d = new D())  // OK
using (C c = new C(d))
{
c.UseLimitedResource();
}

这相当于

using (D d = new D())
{
using (C c = new C(d))
{
c.UseLimitedResource();
}
}

我能想到的最贴切的例子是:

if(someCondition)
if(someOtherCondition)
DoSomething();
else
DoSomethingElse();

else将与哪个if配对?缩进意味着外部的if得到else,但这实际上不是编译器看到它的方式;内心的 if将获得else,而外层的if不会。您必须知道这一点(或者在调试模式下看到它的行为),才能通过检查找出为什么这段代码可能达不到您的期望。如果你懂Python,你会更困惑;在这种情况下,您知道缩进定义了代码块,因此您会期望它根据缩进求值。然而,c#对空格并不在意。

话虽如此,从表面上看,我并不特别同意这个“总是使用括号”的规则。它使代码的垂直噪声非常大,降低了快速读取代码的能力。如果语句是:

if(someCondition)
DoSomething();

... 那么它应该这样写。“总是使用括号”这句话听起来像“数学运算总是用括号括起来”。这将把非常简单的语句a * b + c / d变成((a * b) + (c / d)),引入了缺少闭括号的可能性(许多编码器的麻烦),为什么?操作的顺序是众所周知的,而且执行得很好,所以括号是多余的。你只需要使用圆括号来强制不同于通常应用的操作顺序:例如a * (b+c) / d。块花括号是类似的;使用它们来定义在与默认值不同的情况下想要做什么,并且不是“明显的”(主观的,但通常是相当常识的)。

帮助防止在前面的回答中描述的错误的一个选项是内联您希望在不使用大括号时发生的事情。当您尝试修改代码时,很难不注意到错误。

if (condition) doSomething();
else doSomethingElse();


if (condition) doSomething();
doSomething2(); // Looks pretty obviously wrong
else // doSomethingElse(); also looks pretty obviously wrong

当你完成它时,最好将指针设置为NULL。

下面是一个例子:

A类行为如下:

  1. 分配一块内存
  2. 然后一段时间后,它删除这块内存,但不将指针设置为NULL

B类做以下事情

  1. 分配内存(在这个实例中,它得到的内存块恰好与类a删除的内存块相同)

在这一点上,类A和类B都有指向同一个内存块的指针,就类A而言,这块内存块不存在,因为它已经用完了。

考虑以下问题:

如果在类a中有一个逻辑错误,导致它写入现在属于类B的内存呢?

在这个特定的实例中,您不会得到一个糟糕的访问异常错误,因为内存地址是合法的,而类A现在有效地破坏了类B数据。

类B可能最终崩溃,如果它遇到意外值,当它崩溃时,很有可能,当问题出现在类a时,您将花费相当长的时间在类B中查找这个bug。

如果您已经将删除的内存指针设置为NULL,那么只要类A中的任何逻辑错误试图写入NULL指针,您就会得到一个异常错误。

如果您担心在指针第二次为NULL时使用双重删除会出现逻辑错误,那么可以为此添加assert。

纵观答案,没有人明确地说明了我习惯的那种实践,讲述你的代码的故事:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}

就变成:

int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0) j++;
}

j++放在同一行上作为如果应该向其他任何人发出“我只想让这个块永远增加__abc1”;信号。当然,只有在行代码尽可能简单的情况下,这样做才有意义,因为像仙女提到的那样,在这里设置断点并不是很有用。

事实上,我刚刚遇到了Twitter Storm API的一部分,它在Java中有这种“类型”代码。下面是在幻灯片的第43页上执行的代码的相关片段:

...
Integer Count = counts.get(word);
if (Count=null) count=0;
count++
...

循环块中有两个东西,所以我不会内联该代码。也就是说,从来没有:

int j = 0;
for (int i = 0 ; i < 100 ; ++i) if (i % 2 == 0) j++;

这很糟糕,我甚至不知道它是否有效(如预期的那样);不要这样做。新行和大括号有助于区分独立但相关的代码段,就像散文中的逗号或分号一样。上面的块是一个很长的句子,里面有几个从句和一些其他的语句,从来没有中断或暂停来区分不同的部分。

如果你真的想要向其他人发送一个只有一行的任务,请使用三元操作符或?:形式:

for (int i = 0 ; i < 100 ; ++i) (i%2 ? 0 : >0) j++;

但这接近于代码高尔夫,我认为这不是很好的实践(我不清楚是否应该将j++放在:的一侧)。我以前没有在c++中运行过三元运算符,我不知道这是否有效,但它确实存在

简而言之:

想象一下您的读者(即维护代码的人)如何解释您的故事(代码)。让他们尽可能清楚地知道。如果你知道新手/学生正在维护这个,甚至可能留下尽可能多的{},这样他们就不会感到困惑。

另一个添加花括号的例子。

有一次我在搜索一个bug,发现了这样的代码:

void SomeSimpleEventHandler()
{
SomeStatementAtTheBeginningNumber1;
if (conditionX) SomeRegularStatement;
SomeStatementAtTheBeginningNumber2;
SomeStatementAtTheBeginningNumber3;
if (!SomeConditionIsMet()) return;
OtherwiseSomeAdditionalStatement1;
OtherwiseSomeAdditionalStatement2;
OtherwiseSomeAdditionalStatement3;
}

如果你逐行阅读这个方法,你会注意到方法中有一个条件,如果不为真就返回。但实际上,它看起来像其他100个简单的事件处理程序,它们基于某些条件设置一些变量。有一天,Fast Coder进来了,在方法的末尾添加了额外的变量设置语句:

{
...
OtherwiseSomeAdditionalStatement3;
SetAnotherVariableUnconditionally;
}

因此,setanothervariable无条件地在SomeConditionIsMet()时执行,但速度快的家伙没有注意到它,因为所有的行几乎都是相似的大小,即使返回条件垂直缩进,它也不那么明显。

如果条件返回的格式如下:

if (!SomeConditionIsMet())
{
return;
}

它是非常明显的,快速编码器一眼就能发现它。

我认为第一个比第二个更清楚。它给人一种结束指令的感觉。短代码没问题,但当代码变得复杂时,{...}会有很大帮助,即使它是endifbegin...end

// First
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}




// Second
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
i++;

我必须承认我并不总是在单行中使用{},但这是一个很好的练习。

  • 假设你写的代码没有括号,看起来像这样:

    for (int I = 0;我& lt;100;+ + i) For (int j = 0;j & lt;100;+ + j) < / p > DoSingleStuff ();

一段时间后,你想在j循环中添加一些其他东西,你只是通过对齐来做到这一点,而忘记添加括号。

  • 内存释放更快。假设你有一个很大的作用域,并在里面创建了大数组(没有new,所以它们在堆栈上)。在您离开作用域后,这些数组将从内存中删除。但是有可能你在一个地方使用这个数组,它会在堆栈上停留一段时间,成为某种垃圾。由于堆栈的大小有限且相当小,因此有可能超过堆栈大小。所以在某些情况下,最好写{}来防止这种情况。< >强注意< / >强,这不是针对单行,而是针对以下情况:

    < p >如果(…) { / / SomeStuff…… {//我们没有if, while,等等 / / SomeOtherStuff } / / SomeMoreStuff } < / p >
  • 第三种用法与第二种类似。这不是为了使堆栈更干净,而是为了开放一些函数。如果你在长函数中使用mutex,通常最好在访问数据之前和完成读/写之后锁定和解锁。< >强注意< / >强:如果你自己的类或结构中有构造函数和析构函数来锁定内存,就会使用这种方法。

  • 更重要的是:

    < p >如果(…) 如果(…) SomeStuff (); 其他的 SomeOtherStuff ();//进入第二个if,但是对齐显示它在第一个

总而言之,我不能说,总是使用{}的最佳方式是单行,但这样做并没有什么不好。

如果你编写的是编译代码,但是如果你的代码是被解释的,那么你的代码就会非常非常慢。非常轻微。

总是使用花括号是一个非常简单而可靠的规则。然而,当有很多大括号时,代码可能看起来不优雅。

如果规则允许省略花括号,那么应该有更详细的样式规则和更复杂的工具。否则,它可能很容易导致混乱和混乱(不优雅)的代码。

因此,从使用的其他样式指南和工具中单独查看单个样式规则可能是徒劳的。我将介绍关于规则3的一些其他答案中没有提到的重要细节。

第一个有趣的细节是,该规则的大多数支持者都同意在else的情况下违反它。换句话说,他们不希望得到这样的代码:

// Pedantic rule #3
if ( command == Eat )
{
eat();
}
else
{
if ( command == Sleep )
{
sleep();
}
else
{
if ( command == Drink )
{
drink();
}
else
{
complain_about_unknown_command();
}
}
}

相反,如果他们看到了,他们甚至会建议这样写:

// Not fully conforming to rule #3
if ( command == Eat )
{
eat();
}
else if ( command == Sleep )
{
sleep();
}
else if ( command == Drink )
{
drink();
}
else
{
complain_about_unknown_command();
}

从技术上讲,这违反了规则#3,因为在elseif之间没有花括号,但大多数人认为它更明显,更容易阅读。当试图用不需要动脑筋的工具将规则自动应用到代码库时,规则的这种二元性就会显现出来。的确,为什么要争论呢?只需让一个工具自动应用样式。

第二个细节(也经常被该规则的支持者遗忘)是,可能发生的错觉错误绝不仅仅是因为违反了该规则#3。事实上,这些几乎总是涉及违反规则#1(没有人会争辩)。再一次从自动工具的角度来看,当规则1被违反时,制作一个立即抱怨(甚至修复)的工具并不难,因此可以及时发现大多数错误。

第三个细节(该规则的反对者经常忘记)是由一个分号表示的空语句的令人困惑的性质。大多数具有一定经验的开发人员迟早会被一个放错位置的分号或使用一个分号编写的空语句所迷惑。两个花括号比一个分号更容易识别。

因此,我的建议是,与其同意这些规则,不如同意自动格式化工具的配置,并使其成为构建过程的一部分。这些工具往往比这种争论的参与者更聪明。

因为当你有两个没有{}的语句时,很容易漏掉一个问题。让我们假设代码是这样的。

int error = 0;
enum hash_type hash = SHA256;
struct hash_value *hash_result = hash_allocate();


if ((err = prepare_hash(hash, &hash_result))) != 0)
goto fail;
if ((err = hash_update(&hash_result, &client_random)) != 0)
goto fail;
if ((err = hash_update(&hash_result, &server_random)) != 0)
goto fail;
if ((err = hash_update(&hash_result, &exchange_params)) != 0)
goto fail;
goto fail;
if ((err = hash_finish(hash)) != 0)
goto fail;


error = do_important_stuff_with(hash);


fail:
hash_free(hash);
return error;

看起来不错。它的问题很容易被忽略,特别是当包含代码的函数非常大的时候。问题是goto fail是无条件运行的。你可以很容易地想象这是多么令人沮丧(让你问为什么上次hash_update总是失败,毕竟在hash_update函数中一切看起来都很好)。

然而,这并不意味着我支持在所有地方都添加{}(在我看来,到处都看到{}很烦人)。虽然它可能会导致问题,但它从来没有为我自己的项目,因为我个人的编码风格禁止没有{}的条件,当它们不在同一行时(是的,我同意我的编码风格是非常规的,但我喜欢它,并且我在为其他项目贡献时使用项目的代码风格)。这使得下面的代码很好。

if (something) goto fail;

但下一个不是。

if (something)
goto fail;

有许多可能的方法来编写控制语句;它们的某些组合可能共存而不损害易读性,但其他组合将引起麻烦。的风格

if (condition)
statement;

可以与其他一些编写控制语句的方法很好地共存,但与其他方法就不那么好了。如果多行受控语句被写成:

if (condition)
{
statement;
statement;
}

那么,哪些if语句控制单行,哪些语句控制多行就很明显了。然而,如果多行if语句被写成:

if (condition) {
statement;
statement;
}

那么有人试图扩展一个单语句if结构而不添加必要的大括号的可能性就会高得多。

如果代码库大量使用该形式,则下一行的单语句if语句也可能有问题

if (condition) statement;

我自己的偏好是将语句放在单独的行上通常可以提高易读性,除非有许多if语句具有类似的控制块,例如。

if (x1 > xmax) x1 = xmax;
if (x1 < xmin) x1 = xmin;
if (x2 > xmax) x2 = xmax;
if (x2 < xmin) x2 = xmin;
etc.

在这种情况下,我通常会在这样的if语句组的前面和后面加上一个空行,以便在视觉上将它们与其他代码分开。在同一缩进处以if开头的一系列语句将提供一个清晰的视觉指示,表明有一些不寻常的东西。

在营地呆了10年“总是用背带”;最近,我不再经常使用它们了。 主要是受到Bob叔叔关于如何编写干净代码的争论的启发,我现在认为不使用大括号写代码更具可读性

if(guardClause)
throw new SomeException(..)

Bob大叔认为,在if/for语句中编写多行代码是潜在的可读性问题。

如。

if(someCondition)
{
doTechnicalThingX();
doTechnicalThingY();
doTechnicalThingZ();
}

应该被重构为

if(someCondition)
doFunctionalThingA();

对我来说,不把大括号放在那里是有帮助的,因为我得到提醒,我在if块中写了太多代码。

正如其他人所提到的,我相信代码风格是团队决策。