if, else and Ternary

if runs a block when a bool is true; else and else if add the other paths, and ?: shortens an if that only picks a value.

Syntaxif (boolExpression) { ... } else if (boolExpression) { ... } else { ... } // result = boolExpression ? whenTrue : whenFalse

A program that always does the same thing is rarely useful. if is how a program chooses. You give it a condition, and the code inside the braces runs only when that condition is true.

The condition must be a bool, the type whose only two values are true and false. A number cannot stand in for it. if (count) does not compile in C#; write if (count > 0). An accidental if (x = 1) is rejected for the same reason, because an assignment produces an int here and not a bool.

else and else if

else supplies the path taken when the condition was false. Chaining else if tests conditions in order from the top. The first one that is true wins and the rest are skipped, so an else if never has to repeat the test above it: reaching else if (score >= 70) already means score >= 90 was false.

The ternary conditional

Often both branches do the same job: they pick a value. The conditional operator ?: writes that on one line. string label = passed ? "pass" : "fail"; means exactly what a four-line if/else around the same assignment means. It is called the ternary because it is the one operator that takes three parts: the condition, the value when true, and the value when false.

What trips people up

Braces are optional around a single statement, so in if (ready) Console.WriteLine("a"); Console.WriteLine("b"); the second line runs whatever ready is. Always write the braces. The two results of a ?: must also share a type, so flag ? 1 : "one" is an error.

Example

Example · csharp
int score = 72;

// The condition must be a bool. score >= 90 produces one.
if (score >= 90)
{
    Console.WriteLine("grade: A");
}
else if (score >= 70)
{
    // Reached only when score >= 90 was false.
    Console.WriteLine("grade: B");
}
else
{
    Console.WriteLine("grade: C");
}

// Longhand: four lines whose only job is to pick a value.
string longhand;
if (score >= 70)
{
    longhand = "pass";
}
else
{
    longhand = "fail";
}

// Shorthand: the conditional operator. Same decision, same result.
string shorthand = score >= 70 ? "pass" : "fail";

Console.WriteLine(longhand);
Console.WriteLine(shorthand);

// Output:
// grade: B
// pass
// pass

When to use it

  • Print a different message depending on whether a score is above a pass mark.
  • Choose between "item" and "items" when printing a count.
  • Reject a value outside an allowed range before using it further down.
  • Fall back to a default string when a configuration value is empty.

More examples

Combining conditions instead of nesting

Two conditions that must both hold can be nested or joined with &&. The flat version says the same thing with one level of indentation, and it is what you want whenever the inner if has no else of its own. Reach for nesting only when the outer check has work of its own to do.

Example · csharp
int age = 30;
bool hasTicket = true;

// Nested: every extra check adds a level of indentation.
if (age >= 18)
{
    if (hasTicket)
    {
        Console.WriteLine("admitted");
    }
}

// Flat: && is true only when both sides are true.
if (age >= 18 && hasTicket)
{
    Console.WriteLine("admitted");
}

// Output:
// admitted
// admitted

A ternary inside an interpolated string

Choosing between two words in the middle of a sentence is the clearest case for a ternary, because an if statement would have to break the sentence into pieces. The parentheses are the detail people lose an hour to: without them the colon is read as the start of a number format and the line does not compile.

Example · csharp
int fileCount = 1;

// The parentheses around the ternary are required here: inside an
// interpolation hole a bare : starts a format specifier.
Console.WriteLine($"copied {fileCount} {(fileCount == 1 ? "file" : "files")}");

fileCount = 4;
Console.WriteLine($"copied {fileCount} {(fileCount == 1 ? "file" : "files")}");

// Output:
// copied 1 file
// copied 4 files

A chain of ternaries, and why the if is usually better

A ternary can be chained because its false side is itself an expression. This shows the two forms side by side so you can read either in someone else's code. For three or more outcomes that all produce a value, the switch expression is the form to prefer over both of these.

Example · csharp
int score = 83;

// Chained else if: exactly one branch runs, top to bottom.
string fromIf;
if (score >= 90)
{
    fromIf = "A";
}
else if (score >= 80)
{
    fromIf = "B";
}
else
{
    fromIf = "C";
}

// The same chain as nested ternaries: legal, and harder to read
// as soon as there are more than two outcomes.
string fromTernary = score >= 90 ? "A"
    : score >= 80 ? "B"
    : "C";

Console.WriteLine(fromIf);
Console.WriteLine(fromTernary);

// Output:
// B
// B

Discussion

  • Be the first to comment on this lesson.