When I browsed the stackoverflow website a few days ago, I accidentally saw the question "How to Avoid 'if 'chains" raised by others. I think this is a problem that programmers can easily encounter during programming, I also encountered this programming method when I was reading some source code. Therefore, I would like to summarize this problem.
There are many cases of if nesting. The following lists some situations and provides relatively simple writing methods for your reference:
1. Use a guard to flatten the code
A. The Code is as follows:
if (ok){ DoSomething();}else{ _log.Error("oops"); return;}
Can be replaced:
if (!ok){ _log.Error("oops"); return;} DoSomething(); //notice how this is already farther to the left than the example above
B. The Code is as follows:
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;}
It can be rewritten:
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. When the code is executed without any conditions, the pseudocode is as follows:
bool conditionA = executeStepA();if (conditionA){ bool conditionB = executeStepB(); if (conditionB){ bool conditionC = executeStepC(); if (conditionC){ ... } }}executeThisFunctionInAnyCase();
The executestepx function is executed only when the current condition is set. The executethisfunctioninanycase function must be executed at the end, regardless of whether other conditions are true.
A. Use Conditions and (&) to use the features of short-circuit conditions
if (executeStepA() && executeStepB() && executeStepC()){ ...}executeThisFunctionInAnyCase();
B. Use finally
try{bool conditionA = executeStepA();if (!conditionA) return;bool conditionB = executeStepB();if (!conditionB) return;bool conditionC = executeStepC();if (!conditionC) return;}finally{ executeThisFunctionInAnyCase();}
C. Wrap conditional execution with a function
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. Use the GOTO statement
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. Transfer Using Conditions
bool condition = true; // using only one boolean variableif (condition) condition = executeStepA();if (condition) condition = executeStepB();if (condition) condition = executeStepC();...executeThisFunctionInAnyCase();
F. Usage exception
try { executeStepA(); executeStepB(); executeStepC();}catch (...) {executeThisFunctionInAnyCase();}
G. Use a false Loop
while(true){ bool conditionA = executeStepA();if (!conditionA) break;bool conditionB = executeStepB();if (!conditionB) break;bool conditionC = executeStepC();if (!conditionC) break; break; //important}executeThisFunctionInAnyCase();
H. Use the object Lifecycle
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}
Among them, the simplest is to use short-circuit conditions, and the most complex is to use the object's lifecycle. I have summarized the situation and methods for your reference. Of course, there may be many other situations and solutions, and I hope readers will leave a message.