7

Switch case statements are good to replace nested if statements if we have the same condition but different criteria. But what is a good approach if those nested if statements all have different and unique conditions? Do I have any alternate options to replace a dozen if else statements nested inside each other?

Sample Code:

  • Note: I know this is extremely unreadable - which is the whole point.
  • Note: All conditions are unique.

...

if (condition) {
    // do A
} else {                       
    if (condition) {
        // do B
    if (condition) {
        if (condition) {
            if (condition) {
                // do C
                if (condition) {
                    // do D
                    if (condition) {
                        // do E
                    } else {                                                   
                        if (condition) {
                            // do F
                        }
                    }
                }
            }

            if (condition) {
                // do G
                if (condition) {
                    // do H
                    if (condition) {
                        // do I
                    } else {
                        // do J
                    }
                }
            }
        }
    }
}

Troy Alford
  • 26,660
  • 10
  • 64
  • 82
EP2012
  • 343
  • 1
  • 7
  • 13
  • 7
    If you're in this situation, chances are your design is horribly flawed. – Jordan Kaye Nov 08 '12 at 22:16
  • 1
    As jordan kaye says + IF you really have such complex conditions, if-else will be the easiest way to do so – voluminat0 Nov 08 '12 at 22:18
  • I agree with Mr Kaye. There's a few right answers to this depending on what the condition is, this is not one of them though. It's a bug fest, try write a unit test for it, it might suggest a few things. – Tony Hopkinson Nov 08 '12 at 22:24

6 Answers6

3

The best approach in this case is to chop up the thing into appropriately named separate methods.

Tar
  • 429
  • 2
  • 5
1

In my point of view there exists two main methods to eliminate nested conditions. The first one is used in more special cases when we have only one condition in each nested conditions like here:

function A(){
    if (condition1){
        if (condition2){
            if (condition3){
                // do something
            }
        }
    }
}

we can just go out from the opposite condition with return:

function A(){
    if (condition1 == false) return;
    if (condition2 == false) return;
    if (condition3 == false) return;  
    // do something 
}

The second one is using a condition decomposition and can be treated as more universal than the first one. In the case when we have a condition structure like this, for example:

if (condition1)  
{
    // do this 1
}
else 
{                                                   
    if (condition2) 
    {
        // do this 2
    }                                                    
}

We can implement a variables for each particular condition like here:

bool Cond1 = condition1;
bool Cond2 = !condition1 && condition2;

if (Cond1) { //do this 1 }
if (Cond2) { //do this 2 }
apros
  • 2,848
  • 3
  • 27
  • 31
  • 1
    But how to deal the the do this? – paparazzo Nov 08 '12 at 22:44
  • Yes, I agree that this works only for some special case as in my example where conditions without "else". If conditions nested and without else than we can eliminate a lot of nested branches. – apros Nov 09 '12 at 08:39
1

@Tar suggested one way of looking at it. Another might be.

Invert it.

if (myObject.HasThing1)
{
   if(myObject.HasThing2)
   {
      DoThing1();
   }
   else
   {
      DoThing2();
   }
}
else
{
   DoThing3();
}

could be

DoThing1(myObject.HasThing1);
DoThing2(myObject.HasThing2);
DoThing3(myObject.HasThing3);

So each Do method makes the minimum number of tests, if any fail the it does nothing.

You can make it a bit cleverer if you want to break out of the sequence in few ways.

No idea whether it would work for you, but delegating the testing of the conditions is often enough of a new way of looking at things, that some simplifying factor might just appear as if by magic.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39
1

I had to check this was Stackoverflow not DailyWTF when I saw the code!!

The solution is to change the architecture and use interfaces and polymorphism to get around all the conditions. However that maybe a huge job and out of the scope of an acceptable answer, so I will recommend another way you can kinda use Switch statements with unique conditions:

[Flags]
public enum FilterFlagEnum
{
    None = 0,
    Condition1 = 1,
    Condition2 = 2,
    Condition3 = 4,
    Condition4 = 8, 
    Condition5 = 16,
    Condition6 = 32,
    Condition7 = 64 
}; 


public void foo(FilterFlagEnum filterFlags = 0)
{
        if ((filterFlags & FilterFlagEnum.Condition1) == FilterFlagEnum.Condition1)
        {
            //do this
        }
        if ((filterFlags & FilterFlagEnum.Condition2) == FilterFlagEnum.Condition2)
        {
            //do this
        }
}


foo(FilterFlagEnum.Condition1 | FilterFlagEnum.Condition2);
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
0

If that really is the business logic then the syntax is OK. But I have never seen business logic that complex. Draw up a flow chart and see if that cannot be simplified.

if (condition)  
{
    // do this
}
else 
{                                                   
    if (condition) 
    {
        // do this
    }                                                    
}

can be replaced with

if (condition)  
{
    // do this
}
else if (condition) 
{
    // do this                                                    
}

But again step back and review the design. Need more than just an else if clean up.

paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • Personal thing but I've never liked that one, I always get a uncontrollable urge to add a lot more braces and indent things. :) – Tony Hopkinson Nov 08 '12 at 22:52
0

I feel your pain.

My situation required writing many (>2000) functional tests that have been customer specified for a large, expensive piece of equipment. While most (>95%) of these tests are simple and have a straight forward pass/fail check dozens fall into the "multiple nested if this do that else do something different" at depths similar or worse than yours.

The solution I came up with was to host Windows Workflow within my test application.

All complex tests became Workflows that I run with the results reported back to my test app.

The customer was happy because they had the ability to:

  1. Verify the test logic (hard for non programmers looking at deeply nested if/else C# - easy looking at a graphical flowchart)
  2. Edit tests graphically
  3. Add new tests

Hosting Windows Workflow (in .NET 4/4.5) is very easy - although it may take you a while to get your head around "communications" between the Workflows and your code - mostly because there are multiple ways to do it.

Good Luck

PTRMark
  • 27
  • 2