Перейти к содержимому
Теория · Операторы · урок 4 из 10

Сравнение и логика

Арифметика отвечает числом, а программе часто нужен ответ «да» или «нет». Хватит ли денег на покупку? Исполнилось ли пользователю 18? Такие вопросы задают операторы сравнения.

Представьте контролёра у входа в зал на фильм 18+. Он смотрит в паспорт и отвечает себе на один вопрос: зрителю уже есть 18? Ответов всего два — пустить или не пустить. В C# такой ответ имеет тип bool: true или 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

Давайте разберём программу по строкам:

  1. age >= 18 спрашивает «возраст не меньше 18?» — да, печатается True.
  2. age == 18 спрашивает «возраст ровно 18?» — нет, печатается False.
  3. age != 18 спрашивает «возраст не равен 18?» — да, печатается True.
  4. Результат сравнения можно положить в переменную типа bool, как любое другое значение.

В коде значения пишут с маленькой буквы, true и false, а Console.WriteLine печатает их с большой: True и False.

Операторы сравнения

C# умеет задавать шесть вопросов:

  • == — равно;
  • != — не равно;
  • < — меньше;
  • > — больше;
  • <= — меньше или равно;
  • >= — больше или равно.

Сравнение выполняется после арифметики: в age + 1 >= 18 сначала считается age + 1.

Знак равенства в сравнении двойной. Одиночный = — это присваивание. Путать их — частая ошибка, о ней в конце урока.

Логические операторы

Часто одного вопроса мало. На этот фильм пускают, только если зрителю есть 18 и у него есть билет. Соединять такие вопросы помогают логические операторы:

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

&& — «и»

a && b равно true, только когда истинны обе части. Возраст 20 подходит, а билета нет, поэтому первая строка печатает False.

Так же проверяют, что число лежит в промежутке: age >= 7 && age <= 12. Условие 7 <= age <= 12, как в математике, не скомпилируется: первое сравнение даёт bool, а bool с числом не сравнивают.

|| — «или»

a || b равно true, когда истинна хотя бы одна часть. Скидка положена студенту или пенсионеру. Наш зритель — студент, и строка печатает True.

! — «не»

!a переворачивает значение: !false — это true. Билета нет, поэтому !hasTicket печатает True.

Чтобы перевернуть сравнение, возьмите его в скобки: !(age >= 18). Без скобок ! применится к числу age, и программа не скомпилируется.

Если в одном выражении есть и &&, и ||, поставьте скобки. && выполняется раньше ||, но со скобками порядок видно сразу.

Короткое замыкание

Контролёр не станет спрашивать билет у зрителя, которому нет 18: ответ уже «нет». C# поступает так же. && и || сначала вычисляют левую часть. Если по ней ответ ясен, правую не вычисляют вовсе. Такое правило называют коротким замыканием:

  • && пропускает правую часть, когда левая равна false;
  • || пропускает правую часть, когда левая равна true.

Деление int на ноль — ошибка: программа на ней останавливается. Благодаря короткому замыканию левая часть может защищать правую от такой ошибки:

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

Давайте посмотрим, почему программа не останавливается:

  1. count > 0 равно false, и && не вычисляет total / count. Деления на ноль нет, и строка печатает False.
  2. count == 0 равно true, и || тоже не доходит до деления. Строка печатает True.

Здесь аналогия с контролёром расходится с C#. Контролёр может начать с любого вопроса, а C# всегда вычисляет сначала левую часть, поэтому порядок частей важен. Если написать total / count > 2 && count > 0, деление выполнится раньше проверки, и программа остановится с ошибкой DivideByZeroException.

Короткое замыкание — частый вопрос на собеседовании. Ещё спрашивают, чем && отличается от &. С bool оператор & тоже означает «и», но всегда вычисляет обе части, поэтому count > 0 & total / count > 2 остановит программу той же ошибкой.

Частая ошибка

Вместо сравнения написали присваивание — один знак = вместо двух:

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

Программа не компилируется. age = 18 кладёт 18 в age, и значение всего выражения — число 18. Положить число в переменную типа bool нельзя. Для сравнения нужны два знака: bool isEighteen = age == 18;.

Главное

  • Операторы ==, !=, <, >, <= и >= сравнивают значения и дают bool: true или false.
  • && истинно, когда истинны обе части, || — когда истинна хотя бы одна, а ! переворачивает значение.
  • && и || не вычисляют правую часть, если ответ ясен по левой.
  • Одиночный = присваивает, двойной == сравнивает.