Skip to content
Theory · Operators · lesson 4 of 10

Comparison and logic

Arithmetic answers with a number, but a program often needs a "yes" or "no" answer. Is there enough money for the purchase? Is the user 18 yet? Comparison operators ask such questions.

Imagine an attendant at the door of a screening of an 18+ film. They look at a passport and answer one question for themselves: is the viewer 18 yet? There are only two answers: let them in or not. In C# such an answer has the type bool: true or false.

C#
int age = 20;
Console.WriteLine(age >= 18); // True
Console.WriteLine(age == 18); // False
Console.WriteLine(age != 18); // True
bool isAdult = age >= 18;
Console.WriteLine(isAdult); // True

Let's go through the program line by line:

  1. age >= 18 asks "is the age at least 18?"—yes, so it prints True.
  2. age == 18 asks "is the age exactly 18?"—no, so it prints False.
  3. age != 18 asks "is the age not 18?"—yes, so it prints True.
  4. The result of a comparison can go into a bool variable, like any other value.

In code the values are written in lowercase, true and false, while Console.WriteLine prints them capitalized: True and False.

Comparison operators

C# can ask six questions:

  • ==—equal to;
  • !=—not equal to;
  • <—less than;
  • >—greater than;
  • <=—less than or equal to;
  • >=—greater than or equal to.

A comparison runs after arithmetic: in age + 1 >= 18, age + 1 is computed first.

The equals sign in a comparison is doubled. A single = is assignment. Mixing them up is a common mistake, covered at the end of the lesson.

Logical operators

One question is often not enough. This film lets a viewer in only if they are at least 18 and have a ticket. Logical operators join such questions:

C#
bool hasTicket = false;
bool student = true;
bool pensioner = false;
Console.WriteLine(age >= 18 && hasTicket); // False
Console.WriteLine(student || pensioner); // True
Console.WriteLine(!hasTicket); // True

&&—"and"

a && b is true only when both parts are true. The age 20 fits, but there is no ticket, so the first line prints False.

The same way you check that a number lies in a range: age >= 7 && age <= 12. Writing 7 <= age <= 12, as in math, does not compile: the first comparison gives a bool, and a bool is not compared with a number.

||—"or"

a || b is true when at least one part is true. A discount goes to a student or a pensioner. Our viewer is a student, and the line prints True.

!—"not"

!a flips the value: !false is true. There is no ticket, so !hasTicket prints True.

To flip a comparison, put it in parentheses: !(age >= 18). Without them ! would apply to the number age, and the program would not compile.

When one expression has both && and ||, add parentheses. && runs before ||, but with parentheses the order is visible at once.

Short-circuit evaluation

The attendant will not ask a viewer under 18 for a ticket: the answer is already "no". C# does the same. && and || evaluate the left part first, and if it already settles the answer, they do not evaluate the right part at all. This rule is called short-circuit evaluation:

  • && skips the right part when the left one is false;
  • || skips the right part when the left one is true.

Dividing an int by zero is an error: the program stops on it. Thanks to short-circuit evaluation, the left part can guard the right one against that error:

C#
int count = 0;
int total = 10;
Console.WriteLine(count > 0 && total / count > 2); // False
Console.WriteLine(count == 0 || total / count > 2); // True

Let's see why the program does not stop:

  1. count > 0 is false, and && does not evaluate total / count. There is no division by zero, and the line prints False.
  2. count == 0 is true, and || does not reach the division either. The line prints True.

Here the attendant analogy parts ways with C#. The attendant may start with any question, but C# always evaluates the left part first, so the order of the parts matters. If you write total / count > 2 && count > 0, the division runs before the check, and the program stops with a DivideByZeroException error.

Interviewers like to ask about short-circuit evaluation. They also ask how && differs from &. With bool, the & operator also means "and", but it always evaluates both parts, so count > 0 & total / count > 2 stops the program with the same error.

Common mistake

An assignment is written instead of a comparison—one = sign instead of two:

C#
int age = 20;
bool isEighteen = age = 18; // ✗
Console.WriteLine(isEighteen);
TEXT
error CS0029: Cannot implicitly convert type 'int' to 'bool'

The program does not compile. age = 18 puts 18 into age, and the value of the whole expression is the number 18. A number cannot go into a bool variable. A comparison needs two signs: bool isEighteen = age == 18;.

Key points

  • The operators ==, !=, <, >, <= and >= compare values and give a bool: true or false.
  • && is true when both parts are true, || when at least one is, and ! flips the value.
  • && and || do not evaluate the right part when the left one settles the answer.
  • A single = assigns, a double == compares.