Methods to simplify ugly nested if-else trees in C #

Sometimes I write ugly if-else statements in C # 3.5; I know several different approaches to simplify this with a table-driven development, class hierarchy, anonymous methods, and some others. The problem is that alternatives are still less common than writing traditional ugly if-else statements, because there is no agreement for this.

What depth of nested if-else is normal for C # 3.5? What methods do you expect to see instead of the nested if-else first? second?

if I have ten input parameters with three states in each, I have to match the functions with a combination of each state of each parameter (really less, because not all states are valid, but sometimes there are still many). I can express these states as a hash table key and a handler (lambda) that will be called if the key matches.

It is still combined with data-driven managed tables. ideas and pattern matching.

what I'm looking for extends approaches for C # such as this for scripts (C # 3.5 is more like scripts) http://blogs.msdn.com/ericlippert/archive/2004/02/24/79292.aspx

+4
source share
11 answers

There are very old “formalisms” for trying to encapsulate extremely complex expressions that are evaluated by many, possibly independent variables, such as “decision tables”:

http://en.wikipedia.org/wiki/Decision_table

But, I join the chorus here to repeat the ideas mentioned about the wise use of the ternary operator, if possible, identifying the most unlikely conditions that, if they allow, allow you to complete the rest of the evaluation by excluding them first, and add ... the opposite is that ... trying to separate the most probable conditions and conditions that may allow you to act without testing cases of "fringe".

Miriam's proposal (above) is fascinating, even elegant, as "conceptual art"; and I'm really going to try it, trying to “copy” my suspicion that this will make the code harder to maintain.

My pragmatic side says that there is no answer “one size fits all” in the absence of an example with fairly specific code and a full description of the conditions and their interactions.

I’m a fan of “setting the flag”: this means that someday my application goes into a somewhat less common “mode” or “state”, I set the Boolean flag (which may even be static for the class): for me, it makes writing complex easier, if later, then evaluate.

best bill

+4
source
Good question. "Conditional complexity" is the smell of code. Polymorphism is your friend.

Conditional logic is innocent in its infancy when it is easy to understand and a few lines of code. Unfortunately, he rarely gets old. You implement several new functions and suddenly your conditional logic becomes complex and expansive. [Joshua Kerevsky: Refactoring for Samples]

One of the simplest things you can do to avoid nested blocks is to learn how to use the Protection Clauses .

double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retiredAmount(); return normalPayAmount(); }; 

The other thing I found simplifies everything that makes your code self-documenting, Consolidation of conventions .

 double disabilityAmount() { if (isNotEligableForDisability()) return 0; // compute the disability amount 

Other valuable refactoring methods related to conditional expressions include Decompose Conditional , Replace conditional with visitor , Specification , and Reverse conditional .

+8
source

Simple Take the if body and make a method out of it.

This works because most if statements are of the form:

 if (condition): action() 

In other cases, more specifically:

 if (condition1): if (condition2): action() 

simplify:

 if (condition1 && condition2): action() 
+4
source

I am a big fan of the ternary operator, which many people underestimate. This is great for assigning values ​​to variables based on conditions. like this

 foobarString = (foo == bar) ? "foo equals bar" : "foo does not equal bar"; 

Try this article for more information.

This will not solve all your problems, but it is very economical.

+2
source

I know that this is not the answer you are looking for, but without context, your questions are very difficult to answer. The problem is that the way you reorganize such a thing really depends on your code, what it does, and what you are trying to achieve. If you said that you were checking the type of an object in these conditional expressions, we can throw out an answer, for example, “use polymorphism”, but sometimes you really need some if statements, and sometimes these statements can be reorganized into something simpler, Without Sample code is hard to tell which category you are in.

+2
source

An instructor told me several years ago that 3 is a magic number. And since he applied this in his statements, he suggested that if I need more than 3, then I probably should use the case argument.

  switch (testValue)
    {
       case = 1:
          // do something
          break;
       case = 2:
          // do something else
          break;
       case = 3:
          // do something more
          break;
       case = 4
          // do what?
          break;
       default:
          throw new Exception ("I didn't do anything");
    }

If you are nested expressions containing more than 3 depths, you should probably take this as a sign that there is a better way. Probably, as suggested by Avirdlg, splitting nested if statements into 1 or more methods. If you feel absolutely stuck in several if-else statements, I would wrap all the if-else statements in one method so that it does not mutilate another code.

+2
source

If the goal is to assign a different value to some variable based on the state of various conditional expressions, I use the ternery operator.

If If Else sentences execute separate pieces of functionality. and the conditions are complex, simplified by creating temporary logical variables to store true / false values ​​for complex Boolean expressions. These variables should be appropriately named to represent the business sense of what computes a complex expression. Then use boolean variables in if else synatx instead of complex boolean expressions.

+1
source

One thing I sometimes do is invert the condition, followed by return ; several of these tests in a row can help reduce the nesting of if and else .

+1
source

Not an answer in C #, but you will most likely like pattern matching. When matching patterns, you can accept multiple inputs and perform simultaneous matches on all of them. For example (F #):

 let x= match cond1, cond2, name with | _, _, "Bob" -> 9000 // Bob gets 9000, regardless of cond1 or 2 | false, false, _ -> 0 | true, false, _ -> 1 | false, true, _ -> 2 | true, true, "" -> 0 // Both conds but no name gets 0 | true, true, _ -> 3 // Cond1&2 give 3 

You can express any combination to create a match (it just scratches the surface). However, C # does not support this, and I doubt it will happen any time soon. Meanwhile, there are several attempts to try this in C #, for example here: http://codebetter.com/blogs/matthew.podwysocki/archive/2008/09/16/functional-c-pattern-matching.aspx . Google may be many more; it might suit you.

+1
source

try using templates such as strategy or team

0
source

In simple cases, you can get by with basic functional decomposition. For more complex scenarios, I used the Specification Template with great success.

0
source

All Articles