Do more in less time. Block distracting websites with Cold Turkey Pro (Windows, Mac) »

Make complex C# if statements easier with nested if statements

When we program if statements there’s typically just one or two Boolean expressions. But as our program evolves we add more and more true/false conditions to the if statement. Over time, that code becomes harder to read and comprehend. So how can we make complex if statements easier to understand?

Simplify complex ifs with C#’s nested if statements

Thanks to if statements our program can make decisions while it runs. That makes our code flexible and adapt to inputs. But sometimes program decisions are long and complex. A complex if statement typically has multiple true/false expressions combined with logical operators and grouped with parentheses. That not only makes them hard to read, but also more difficult to understand and debug.

There are several ways to make complex if statements easier to work with. When we for instance use interim variables, some true/false expressions can be replaced with a clear name. Another way that reduces the complexity is to move part of an if statement’s true/false expressions into a nested if statement.

A nested if statement is an if statement placed inside another, and that allows us to handle more complex conditions easier (Dorman, 2010; Liberty & MacDonald, 2009). A nested if statement depends on the if statement above it. That is, before our program evaluates a nested if statement its preceding if statement has to evaluate to true.

That feature can make a complex if statement easier to read: when we split part of the Boolean expressions into a nested if statement, the original if statement becomes easier to understand while the behaviour of the code does not change. Let’s take a closer look.

Replacing C#’s if with nested if: a requirement

To split part of a complex if statement into a nested if statement there’s one requirement: the original if statement needs to have the logical AND operator (&&) in its condition. (See combine if statement conditions with logical operators for more on the && operator.)

We need that && operator for a simple reason: a nested if statement behaves likes that logical operator does. And so to decide where to split up a complex if statement, we simply look at the location of the && operator inside the if statement’s condition.

Let’s see why that’s the case. The logical AND operator (&&) only returns true when both its left and right value are true too (Sharp, 2013). We see a similar thing with the code of a nested if statement: that code only runs when both the nested if statement and the if statement above it evaluate to true.

Say we have an if statement like this:

if (condA && condB)
{
    // ...
}

We can rewrite this if statement to use a nested if statement like so:

if (condA)
{
    if (condB)
    {
        // ...
    }
}

But this only applies when the original if statement uses the && operator. Say our if statement uses the logical OR operator (||) instead, like this:

if (condA || condB)
{
    // ...
}

Here we check if condA or (||) condB is true before we run the if statement’s code. Since the logical OR operator (||) returns true when its left or right value is true (Sharp, 2013), only one of those expressions has to be true. That means we cannot replace this if statement in a clean way with a nested if statement.

Tips for better code with split C# if statements

When we split an if statement into one or two nested if statements, the true/false expression(s) we evaluate first can impact code performance. Say our top if statement evaluates a condition that’s easily computed, but not that often true. In most cases then our nested if statement doesn’t run, and so our program doesn’t need to evaluate the true/false conditions of the nested if statement. This tip gives a noticeable improvement when the nested if statement for instance checks database values or downloads and processes an internet file.

Another consideration is what makes the if statement unclear to begin with. With a lot of expressions combined with the logical AND operator (&&), splitting some in a nested if statement makes sense. But not all if statements are unclear because of their number of expressions. Some also lack parentheses that make code easier to read . And others could be easier to understand with interim variables . This means we don’t always have to split up an if statement but have other options to improve code readability too.

And last but not least, we have to find a balance between a single if statement with a complex condition and multiple nested if statements with easy-to-read conditions. Typically, improving the readability of a complex if statement with a nested if statement is a good idea. But with too many nested if statements the code becomes harder to read and follow.

Typically more than 2 nested if statements make code less readable because each nested if statement adds additional indentation.

Example: clarify a complex if with C#’s nested if statement

As an example, let’s look at the if statement below. Here the if statement contains 5 different Boolean expressions, combined with the logical AND (&&) and OR (||) operators. The if statement has understandable variable names for those familiar with racing. But still, this short example isn’t that clear.

if (((ageTires > 15 || gapOpponent >= 22 || lowGrip) && (pitStopsRemaining > 0)) &&
    (tireWear == TireWear.High) && (lapTime < (avgLapTime * 0.98)))
{
    Console.WriteLine("Notify the driver. It's time for a pit stop!");
}

We can imagine that this if statement helps a racing team decide when to perform a pit stop to give a racing car new tires.

For this we look at the age of the tires in laps (ageTires), the gap to the driver’s main opponent in seconds (gapOpponent), or whether the driver complains about low grip (lowGrip). We also consider how many stops the driver still has to take (pitStopsRemaining). Then we look if the tires are worn out (TireWear.High) and whether the last lap time was more than 2% below our driver’s average lap time.

To clarify this if statement we can split part of its condition into a nested if statement. One way to do so is when we categorise the true/false conditions like this:

// Verify the pit stop regulatory requirements and window
if ((pitStopsRemaining > 0) && ((ageTires > 15) || (gapOpponent >= 22) || lowGrip))
{
    // Check the current tire performance
    if ((tireWear == TireWear.High) && (lapTime < (avgLapTime * 0.98)))
    {
        Console.WriteLine("Notify the driver. It's time for a pit stop!");
    }
}

Here we divide all true/false expressions from the previous if statement in two parts. With the first if statement we check the pit stop requirements: the number of stops still to do, tire age, opponent gap, and whether the car’s grip is low enough to need fresh tires.

When that condition evaluates to true, the if statement’s code executes. That code has a nested if statement take a closer look at the tire performance. When the tire wear is high and the lap time considerably below the average time, we use the Console.WriteLine() method to print a message saying it’s time for a pit stop.

Even though this code performs the same as the previous single if statement, it in effect categorises the different conditions that we look at before planning a pit stop. This makes code easier to read and understand, both for people new to the code and for ourselves when we revisit our code a couple of months from now.

Summary

With if statements our program takes decisions while it runs. But sometimes their complexity doesn’t make for readable code. And nor does it make code easier to understand and debug. Luckily we can make an if statement easier to understand. For that we split part of its Boolean expressions into a nested if statement. A nested if statement is an if statement placed inside another. That means for its code to run, the condition of the above if statement also has to be true.

Before we can simplify a complex if statement by adding a nested if statement, the original if statement’s condition needs to use the logical AND operator (&&). That operator combines two Boolean expressions and only returns true when its left and right value are true too.

This is just like how an if statement and nested if statement both need a true condition before the nested if statement’s code runs. And so when we want to split up a complex if statement, we’ll have to look at the location of the && operator inside its true/false condition.

Don’t overdo splitting up an if statement because too many nested if statements make code harder to understand. And when possible, include the most restrictive Boolean expression inside the first if statement. This way our program doesn’t have to evaluate the nested if statement in most cases (because the if statement above it already evaluated to false).

Learn more

References

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN: Sams/Pearson Education.

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

Sharp, J. (2013). Microsoft Visual C# 2013 Step by Step. Microsoft Press.