Until now, your programs always take the same path from top to bottom. A program only becomes useful when it reacts to values: Is the input a number? Is it cold outside? Did someone type “yes”? That’s what conditions and branches are for.
Comparisons are true or false
A comparison gives you a value of type bool: true or false.
| Symbol | Meaning |
|---|---|
== |
is equal to |
!= |
is not equal to |
< and > |
is less than, is greater than |
<= and >= |
is less than or equal to, is greater than or equal to |
// comparisons.cs
int degrees = 73;
Console.WriteLine(degrees > 68);
Console.WriteLine(degrees == 73);
Console.WriteLine(degrees != 73);
Console.WriteLine(degrees <= 50);
string color = "red";
Console.WriteLine(color == "red");
Console.WriteLine(color == "Red");
True
True
False
False
True
False
On the screen, C# writes True and False with a capital letter; in code, you write true and false in lowercase. And once more,
because it gets mixed up so often: a single = puts a value into a variable, the double == compares. The last line also shows that
upper and lower case count when you compare texts.
if and else
With if, a program runs a block only when a condition is true. The block after else runs when it is false:
// jacket.cs
Console.Write("How many degrees is it outside? ");
int degrees = int.Parse(Console.ReadLine() ?? "");
if (degrees < 55)
{
Console.WriteLine("Take a jacket.");
}
else
{
Console.WriteLine("A sweater will do.");
}
Console.WriteLine("Have a nice day!");
How many degrees is it outside? 46
Take a jacket.
Have a nice day!
The condition goes in parentheses, the statements go in curly braces { }. A pair of braces with everything inside is called a
block. The last line comes after both blocks, so it always runs. The indentation of four spaces is for the people who read the
code. The compiler doesn’t need it, but you do: it shows at a glance what belongs to what.
More than two paths
With else if, you check several conditions one after another. The first one that is true wins. If none is true, the else block
runs:
// traffic-light.cs
Console.Write("What color is the traffic light? ");
string color = (Console.ReadLine() ?? "").Trim().ToLower();
if (color == "red")
{
Console.WriteLine("Stop and wait.");
}
else if (color == "yellow")
{
Console.WriteLine("Careful, it is about to change.");
}
else if (color == "green")
{
Console.WriteLine("You may go.");
}
else
{
Console.WriteLine($"I don't know the color \"{color}\".");
}
What color is the traffic light? Yellow
Careful, it is about to change.
The second line holds two helpers for texts. Trim() removes spaces at the start and the end, and ToLower() makes every letter
lowercase. That way, the input “ Yellow ” still matches “yellow.” People don’t always type what a program expects. A good program is
ready for that.
Combining conditions
Sometimes a decision depends on more than one thing. There are three ways to combine conditions:
&&means “and.” The whole thing is true when both sides are true.||means “or.” The whole thing is true when at least one side is true.!means “not.” It turns true into false and false into true.
// movie-theater.cs
int age = 14;
bool withAdult = true;
bool hasTicket = true;
if (hasTicket && (age >= 16 || withAdult))
{
Console.WriteLine("Enjoy the movie!");
}
else
{
Console.WriteLine("Sorry, not this time.");
}
if (!hasTicket)
{
Console.WriteLine("The box office is on the left.");
}
Enjoy the movie!
In words: anyone who has a ticket and is either at least 16 or comes with an adult gets in. The parentheses around the “or” part
matter, because without them, C# would work out && first. When in doubt, add one pair of parentheses too many rather than one too
few. Change the three values at the top and predict what comes out before you run it.
Checking input with int.TryParse
In the last lesson, your program crashed when it got a word instead of a number. int.TryParse tries the conversion without crashing.
It returns true if it worked, and then puts the number into the variable after out:
// safe-input.cs
Console.Write("How old are you? ");
string input = Console.ReadLine() ?? "";
if (int.TryParse(input, out int age))
{
Console.WriteLine($"Next year you will be {age + 1}.");
}
else
{
Console.WriteLine($"\"{input}\" is not a whole number. Please use digits, for example 36.");
}
How old are you? thirty-six
"thirty-six" is not a whole number. Please use digits, for example 36.
out int age means: “Create a new variable age right here, and TryParse puts the result into it.” Use age only inside the if
block, because only there do you know that the conversion worked. From now on, every program in this course reads numbers this way.
Many fixed cases: switch
When a value has many fixed options, a long chain of else if gets hard to read. For cases like this, there is the
switch expression:
// day-of-week.cs
int day = 3;
string name = day switch
{
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6 => "Saturday",
7 => "Sunday",
_ => "no day of the week",
};
Console.WriteLine($"Day {day} is a {name}.");
Day 3 is a Wednesday.
Each line means: “If the value is the one on the left, the result is the one on the right.” The underscore _ catches everything not
listed above it, like else. If you forget it, the compiler warns you that not all cases are covered.
Exercise 1
Write even-odd.cs. The program asks for a whole number and says whether it is even or odd. If the input isn’t a number, it says so in
a friendly way. Tip: a number is even when dividing it by 2 leaves no remainder.
Solution 1
// even-odd.cs
Console.Write("A whole number, please: ");
string input = Console.ReadLine() ?? "";
if (int.TryParse(input, out int number))
{
if (number % 2 == 0)
{
Console.WriteLine($"{number} is even.");
}
else
{
Console.WriteLine($"{number} is odd.");
}
}
else
{
Console.WriteLine("Sorry, that was not a whole number.");
}
A whole number, please: 17
17 is odd.
Here one if sits inside another. That’s allowed and common. The indentation shows that the question “even or odd?” is only asked
when a number came in at all. Try negative numbers and 0 as well.
Exercise 2
Write admission.cs. The program asks for an age and names the right ticket:
- under 6: “Free admission”
- from 6 to 17: “Child ticket”
- 65 and over: “Senior ticket”
- everyone else: “Adult ticket”
An age below 0, or input that isn’t a number, should give a message.
Solution 2
// admission.cs
Console.Write("How old are you? ");
string input = Console.ReadLine() ?? "";
if (!int.TryParse(input, out int age) || age < 0)
{
Console.WriteLine("Please enter an age as a whole number, 0 or more.");
}
else if (age < 6)
{
Console.WriteLine("Free admission");
}
else if (age <= 17)
{
Console.WriteLine("Child ticket");
}
else if (age >= 65)
{
Console.WriteLine("Senior ticket");
}
else
{
Console.WriteLine("Adult ticket");
}
The order of the conditions matters. The check says age <= 17, not age >= 6 && age <= 17, because the chain only gets that far
when age < 6 was already false. The first condition also shows how ! and || work together: the message appears when the
conversion didn’t work or the age is negative. Because || checks from left to right and stops as soon as one side is true,
age < 0 is only checked when there really is a number in age.
Test the boundaries: 5, 6, 17, 18, 64, 65. Boundaries are where most mistakes hide.
Exercise 3
Write leap-year.cs. It asks for a year and says whether it is a leap year. The rule of the Gregorian calendar: a year is a leap year
if it can be divided by 4 but not by 100. Years that can be divided by 400 are leap years all the same. Check your program with 1900
(not a leap year), 2000 (leap year), 2024 (leap year) and 2025 (not one).
Solution 3
// leap-year.cs
Console.Write("Which year? ");
string input = Console.ReadLine() ?? "";
if (int.TryParse(input, out int year))
{
bool leapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
if (leapYear)
{
Console.WriteLine($"{year} is a leap year.");
}
else
{
Console.WriteLine($"{year} is not a leap year.");
}
}
else
{
Console.WriteLine("That was not a year.");
}
Which year? 1900
1900 is not a leap year.
Here the condition is first stored in a bool variable with a name that says what it means. That makes the if below it easy to read,
and it’s a good trick for any longer condition.
What you can do now
- You compare values with
==,!=,<,>,<=and>=and know that the result is abool. - You use
if,else ifandelseto build programs that take different paths. - You combine conditions with
&&,||and!and add parentheses where they are needed. - You read numbers with
int.TryParseand respond to wrong input. - You express fixed cases with a
switchexpression. - You test at the boundaries.
Read more
- Branches and loops: conditions and loops in Microsoft’s tutorial series.
- Add decision logic to your code in C#: a module with exercises
on
if,else ifandelse. - Evaluate Boolean expressions to make decisions in C#: more about conditions and how to combine them.