当代码流是这样的:
if(check())
{
...
...
if(check())
{
...
...
if(check())
{
...
...
}
}
}
我通常看到这种方法可以避免上述混乱的代码流:
do {
if(!check()) break;
...
...
if(!check()) break;
...
...
if(!check()) break;
...
...
} while(0);
有什么更好的方法可以避免这种工作/黑客,从而使其成为更高级别(行业级别)的代码?
任何跳出盒子的建议都是欢迎的!
当然不是答案,而是一个答案(为了完整起见)
而不是:
do {
if(!check()) break;
...
...
if(!check()) break;
...
...
if(!check()) break;
...
...
} while(0);
你可以这样写:
switch (0) {
case 0:
if(!check()) break;
...
...
if(!check()) break;
...
...
if(!check()) break;
...
...
}
这仍然是一个伪装的goto,但至少它不再是一个循环。这意味着你不需要非常仔细地检查是否有一些继续隐藏在块的某处。
构造也非常简单,您可以希望编译器会优化它。
正如@jamesdlin所建议的,你甚至可以把它隐藏在一个宏后面
#define BLOC switch(0) case 0:
然后像这样使用它
BLOC {
if(!check()) break;
...
...
if(!check()) break;
...
...
if(!check()) break;
...
...
}
这是可能的,因为C语言语法期望在开关之后有一个语句,而不是一个括号中的块,并且您可以在该语句之前放置一个case标签。到目前为止,我还没有看到允许这样做的意义,但在这种特殊情况下,将开关隐藏在一个漂亮的宏后面是很方便的。
我不是特别喜欢在这种情况下使用break或return的方法。考虑到通常当我们面对这样的情况时,这通常是一个比较长的方法。
如果我们有多个出口点,当我们想要知道什么会导致某些逻辑被执行时,这可能会造成困难:通常情况下,我们只是继续向上包含该逻辑的块,而这些块的标准告诉我们情况:
例如,
if (conditionA) {
....
if (conditionB) {
....
if (conditionC) {
myLogic();
}
}
}
通过查看封闭块,很容易发现myLogic()只在条件a和条件b和条件c为真时发生。
当有早期的回报时,它变得不那么明显:
if (conditionA) {
....
if (!conditionB) {
return;
}
if (!conditionD) {
return;
}
if (conditionC) {
myLogic();
}
}
我们不能再从myLogic()向上导航,查看封闭块来找出条件。
我使用了不同的变通方法。这是其中之一:
if (conditionA) {
isA = true;
....
}
if (isA && conditionB) {
isB = true;
...
}
if (isB && conditionC) {
isC = true;
myLogic();
}
(当然欢迎用同一个变量替换所有isA isB isC)
这样的方法至少会让代码的读者知道,当isB && conditionC时执行myLogic()。给读者一个提示,他需要进一步查找使isB为真的原因。