使用do-while(false)的好处是什么?

22

当查看由另一位员工处理的一些代码时,我发现有很多用这种写法编写的代码:

do{
    ...
}while(false);

这样做有什么优势吗?

下面是代码中正在发生的更多骨架内容:

try{
    do{
        // Set some variables

        for(...) {
            if(...) break;
            // Do some more stuff
            if(...) break;
            // Do some more stuff
        }
    }while(false);
}catch(Exception e) { 
    // Exception handling 
}

更新:

C++版本:
do-while-false循环常见吗?


7
主要的优点是它能告诉你需要与哪个员工进行交流! - Mitch Wheat
11
为什么要关闭投票?这绝对是一个真正的问题! - Dominic Rodger
10
在我的看法中,这看起来完全荒谬无比。 - Mitch Wheat
1
另一位员工?就是你旁边的同事?可以跟他们交流并可能得到回答的人? - kdgregory
也许编码人员使用它来缩小本地变量范围,没有意识到您可以使用裸{}做同样的事情。 - james
显示剩余5条评论
14个回答

27

可能是为了能够随时跳出“循环”,例如:

do
{
    ...
    if (somethingIsWrong) break;
    //more code
    ...
}
while(false);

但是正如其他人所说,我不会这样做。


6
好的,让我们绕过我们的语言没有goto的限制来进行编程。 - Michael Myers
4
哇,这就是 Java 风格的跳转语句!(但它更适合作为一个带有条件返回的函数实现) - moonshadow
2
@mmyers:这更或多或少与(滥用)异常来进行流程控制相同。 - M4N
2
我相当确定让这段代码更加复杂的唯一方法是在其中间使用 try {} finally {} 块。这段代码让我感到悲伤。 - Malaxeur
3
@Tom,因为你看到那个“return”语句就知道你所处的方法。但是如果你看到“break”语句,通常会想“哦,这是要跳出循环 - 等等,循环?”,我认为这会引起困惑。 - Johannes Schaub - litb
显示剩余7条评论

17
在Java中,没有必要这样做。
在C语言中,定义宏时常常使用这种习惯用法:
考虑以下代码:
#define macro1 doStuff(); doOtherStuff()
#define macro2 do{ doStuff(); doOtherStuff(); } while( false )

if( something ) macro1; // only the first statement in macro1 is executed conditionally
if( something ) macro2; // does what it looks like it does

...但是在 C 语言中,宏定义往往容易引发问题,尽可能避免使用。

你的同事是否有 C 语言背景?


14

没有优势。不要尝试。


8
它的优点是能激怒迈尔斯。这不足以成为做这件事的理由吗? - Pesto
2
我并不感到愤怒。但是,我也不必维护这个人的代码。 - Michael Myers
3
你应该感到愤怒了。难道你没有看到他的while循环!;) - Mitch Wheat

7

这个功能可以用于跳到一个块的结尾,从而避免大量嵌套的if/then块。

do {
    if (done()) continue;
    // do a bunch of stuff
    if (done()) continue;
    // do a bunch more stuff
    if (done()) continue;
    // do even more stuff
} while (false);

4

这在C语言中用于定义宏内部的块。例如请查看此处

例如,以下代码是无效的:

#define f(x) { g(x); h(x); }

if (x >= 0) f(x); else f(-x);

但使用这个定义,它将有效:
#define f(x) do { g(x); h(x) } while(false)

Java没有宏,即使有,在Java中在闭合大括号后面加上分号也是合法的,因此不需要它。 - Pete Kirkham
有分号是合法的,除非你想在那里放置“else”。 if () {}; else {} - 是不合法的。 - alex
你可能想要进一步阐述。 - Tom Hawtin - tackline
这似乎是最合乎逻辑的解释,并支持@moonshadow的观点。 - ericp

3

虽然这个方法并没有什么用,但程序员可以使用多个break命令来进行一些奇怪的异常处理。

do{
if(<something>){...}else{break}
if(<something else>){...}else{break}
...
}while(false)

虽然有些傻,但我曾在一份旧的C程序中发现过类似的东西。


今天刚遇到这个问题。在C++方法的主体中发现了这个结构,我想知道这是什么鬼?谷歌把我带到了这里,这似乎是最有可能的答案。原始编码器在do..while块中有多个if (errorCond) { /* do something */ break; }语句。我唯一能看到的优点是它提供了一个从方法中返回的点(在我正在查看的代码中,在方法的末尾),而不是几个点。我不会这样编码,但我可以理解为什么要这样做。 - Jon

2
你的直觉是正确的。那样做完全没有用处。
可能最初编写代码的人使用了除false以外的其他条件,只是将其更改为false而不是删除整个块,以保留该代码的“历史”。然而,这只是抓住稻草。坦白地说,这只是一个明显的同义反复的例子,在代码中没有任何意义。

哇,突然的负评是怎么回事?当你给出负评时留下评论是礼貌的,而且原因还没有被解释! - Noldorin
+1 可以让您的帖子再次上升。然而,我可以想象有些人会对您与“逻辑重言式”的类比感到困惑,并认为您在谈论“false”是一个重言式。您能否详细说明一下这个类比? - Johannes Schaub - litb
@litb:谢谢。是的,也许我在那里使用了错误的同义反复。从常识上讲,它肯定是一种同义反复:你只需编写一次代码,然后再添加do { ... } while (false)(不必要地)指定它应该被添加一次。 - Noldorin

1
我多年来一直使用这种约定!当您有一个处理和/或条件检查的“管道”时,它非常有用。它简单地避免了多层嵌套的if()语句,从而使代码(更)易于阅读。是的,有替代方案,比如try/catch,我只在某些薄/低级别的情况下使用这种样式。
我会用类似以下的注释来开始“循环”(实际上从未循环)...
// Error loop (never loops)

错误循环是...
set errorCode = fail;
do {
  if (this)
    break;

  if (that)
    break;

  // Success
  set errorCode = ok;

  // Alternative Success
  errorCode = doWhatever();
} while (false);

如果您有一堆嵌套的if()语句,且缩进超过3个级别,请考虑使用此样式。我在Perl、C/C++、Java和Delphi/Pascal中使用了这种约定。

1

它可以用于跳过一些代码的执行(比如像goto之类的东西),但当我再次查看时,似乎在do-while中有一个for循环(其中if(...) break;语句)。否则,我会说这将是Java版本的goto...


1
在除了C/C++之外的几乎所有编程语言中,这并不提供任何战术优势。
在C/C++中,有一种情况是使用宏时,do/while(false)使得将宏安全地扩展为多个语句更加容易。当宏看起来像普通函数调用时,这是很有优势的。

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