標籤:stackoverflow c if 編程 boolean
前幾日在瀏覽stackoverflow網站時,偶然看到別人提的“How to avoid ‘if’ chains” 的問題,覺得這是一個編程人員在編程時很容易就碰到的問題,而且我自己在看一些源碼時也遇到過這種編程方式,因此,對這個問題進行一點總結。
if嵌套的情況很多,下面列出一些情況,並給出了相對來說比較簡潔的書寫方式以供參考:
1、使用一個guard來使用代碼變得平坦
a、代碼如下:
if (ok){ DoSomething();}else{ _log.Error("oops"); return;}
可以替換成:
if (!ok){ _log.Error("oops"); return;} DoSomething(); //notice how this is already farther to the left than the example above
b、代碼如下:
ok = DoSomething1();if (ok){ ok = DoSomething2(); if (ok) { ok = DoSomething3(); if (!ok) { _log.Error("oops"); //Tip of the Arrow return; } } else { _log.Error("oops"); return; }}else{ _log.Error("oops"); return;}
可以改寫成:
ok = DoSomething1();if (!ok){ _log.Error("oops"); return;} ok = DoSomething2();if (!ok){ _log.Error("oops"); return;} ok = DoSomething3();if (!ok){ _log.Error("oops"); return;} ok = DoSomething4();if (!ok){ _log.Error("oops"); return;}
2、最後有非條件執行代碼的情況,虛擬碼如下:
bool conditionA = executeStepA();if (conditionA){ bool conditionB = executeStepB(); if (conditionB){ bool conditionC = executeStepC(); if (conditionC){ ... } }}executeThisFunctionInAnyCase();
函數executeStepX若且唯若前面的條件成立時才執行,而函數executeThisFunctionInAnyCase則在最後必需執行,而不管其它條件是否成立。
a、使用條件與(&&),利用條件短路的特性
if (executeStepA() && executeStepB() && executeStepC()){ ...}executeThisFunctionInAnyCase();
b、使用finally
try{bool conditionA = executeStepA();if (!conditionA) return;bool conditionB = executeStepB();if (!conditionB) return;bool conditionC = executeStepC();if (!conditionC) return;}finally{ executeThisFunctionInAnyCase();}
c、將條件執行用一個函數包起來
void foo(){ bool conditionA = executeStepA(); if (!conditionA) return; bool conditionB = executeStepB(); if (!conditionB) return; bool conditionC = executeStepC(); if (!conditionC) return;}void bar(){ foo(); executeThisFunctionInAnyCase();}
d、使用goto語句
int foo() { int result = /*some error code*/; if(!executeStepA()) goto cleanup; if(!executeStepB()) goto cleanup; if(!executeStepC()) goto cleanup; result = 0;cleanup: executeThisFunctionInAnyCase(); return result;}
e、利用條件的傳遞
bool condition = true; // using only one boolean variableif (condition) condition = executeStepA();if (condition) condition = executeStepB();if (condition) condition = executeStepC();...executeThisFunctionInAnyCase();
f、使用異常
try { executeStepA(); executeStepB(); executeStepC();}catch (...) {executeThisFunctionInAnyCase();}
g、使用假迴圈
while(true){ bool conditionA = executeStepA();if (!conditionA) break;bool conditionB = executeStepB();if (!conditionB) break;bool conditionC = executeStepC();if (!conditionC) break; break; //important}executeThisFunctionInAnyCase();
h、利用對象的生命週期
class MyContext{ ~MyContext() { executeThisFunctionInAnyCase(); }}void MainMethod(){ MyContext myContext = new MyContext(); bool conditionA = executeStepA();if (!conditionA) return;bool conditionB = executeStepB();if (!conditionB) return;bool conditionC = executeStepC();if (!conditionC) return; //DoSomethingNoMatterWhat will be called when myContext goes out of scope}
其中,最簡單的是利用條件短路,而最複雜的是利用對象的生命週期。總結了這此情況和方法供大家參考,當然,可能還有很多其它的情況和處理方法,希望讀者踴躍留言。