C# from the ground up

Decisions: if, else and switch

Conditions that are true or false, chains with else if, combinations with and and or, and the switch that picks one branch to run.

Part 4 of 13

Beginner16 min readBack to Courses

A condition is a question with one answer

A condition is an expression that is either true or false: score >= 50, name == "Ada", visits > 0. The comparison operators are == for equal, != for not equal, and <, >, <=, >= for size. The answer is a bool, and if runs the block under it only when that answer is true.

Text compares with == as well, which is worth a moment: strings are compared by their characters, so "Ada" == "Ada" is true. One warning that catches everyone once: a single = assigns and a double == compares. if (score = 50) is not a question, it is an assignment, and the compiler refuses it in a C# condition.

Chains, and combining two questions

else if adds another question for the cases the first one missed, and a final else catches whatever is left. The order matters, because the first true branch wins and the rest are never looked at: put the strictest test at the top.

Two conditions combine with && for "both" and || for "either", and ! flips a true to false. This is how a rule reads aloud: score >= 50 && grade != "F" is "passed and not failed". For a short either-or value there is the ternary: var label = score >= 50 ? "pass" : "fail"; — a question, a value when true, a value when false.

The ternary is an expression, so both arms have to produce a value of the same type, and the whole thing has to be used: assigned, printed or passed. A ternary on a line of its own is usually a sign that an if was meant. Nesting one ternary inside another works, and it is the fastest way to make a condition unreadable; a chain of else if says the same thing with room to breathe.

switch picks one branch

When one value leads to several outcomes, switch reads better than a long chain of else if. Each case names a value to match, break ends the branch, and default is the branch for everything else. Without the break, C# refuses to compile rather than running into the next branch, so the mistake is caught for you.

Newer versions of C# can also write a switch as a single expression that hands back a value. The compiler in this sandbox is older than that, so this course writes the statement form — the same decision, spelled out in full.

A chain, a combination and a switch

using System;

class Program
{
    static void Main()
    {
        var score = 82;
        string grade;

        if (score >= 90) { grade = "A"; }
        else if (score >= 80) { grade = "B"; }
        else { grade = "C"; }

        // Both questions have to be true.
        var good = score >= 80 && grade != "C";

        // Either side is enough.
        var perfect = score == 100 || score == 0;

        // A short decision can be written as a value.
        var note = score >= 50 ? "passed" : "failed";

        switch (grade)
        {
            case "A":
                Console.WriteLine("Gold");
                break;
            case "B":
                Console.WriteLine("Silver");
                break;
            default:
                Console.WriteLine("Bronze");
                break;
        }

        Console.WriteLine(note + " " + good + " " + perfect);
    }
}

A grade, decided three ways

Run it, then change the score to 95 and watch the three lines change. Then make the ternary give a C for anything under 50, and add a case for C to the switch.

Output
Click "Run" to execute your code

One equals sign assigns and two compare. If a condition feels wrong, check the sign before checking the logic.

Short-circuit, and why the order matters

&& and || do not always evaluate both sides. With &&, if the left side is false the answer is already false, so the right side is skipped. With ||, a true left side is enough. The language guarantees this, and careful code uses it.

That is how a guard works: if (name != null && name.Length > 0) is safe because the length is only read when the name exists. Reverse the two tests and the same line throws. The order of a condition is part of its meaning, not a matter of taste.

switch compares constant values

A switch is not a chain of arbitrary questions. Each case names a constant value, and the switch compares the one expression against each in turn. That is why a case cannot be score >= 90; a range belongs in an if.

The expression can be an integer, a char, a string or an enum. When no case matches, default runs, and it is good practice to include one even when you think every value is covered, because a value from outside your program will eventually prove you wrong.

Three decision mistakes: using & or | instead of && and ||, since the single forms evaluate both sides and do not short-circuit; forgetting break, which C# refuses to compile rather than letting one case run into the next; and expecting a switch case to accept a range such as score >= 90.

Try these next

  • Write a condition that checks a name is not null before asking for its length, then swap the order and see the failure.
  • Turn a three-branch if chain into a switch on a string, and add a default that prints a fallback.
  • Use the ternary to choose between two labels, then rewrite it as an if and compare which reads better.

A delivery charge with two rules

Run it, then change the day to Monday and the member flag to false. Predict the charge before each run, and add a rule that makes Sunday delivery free.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

Which operator asks whether two values are equal?