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.
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.
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
ifchain into aswitchon a string, and add adefaultthat prints a fallback. - Use the ternary to choose between two labels, then rewrite it as an
ifand 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.
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?
