Сравнение и логика
Арифметика отвечает числом, а программе часто нужен ответ «да» или «нет». Хватит ли денег на покупку? Исполнилось ли пользователю 18? Такие вопросы задают операторы сравнения.
Представьте контролёра у входа в зал на фильм 18+. Он смотрит в паспорт и отвечает себе на один вопрос: зрителю уже есть 18? Ответов всего два — пустить или не пустить. В C# такой ответ имеет тип bool: true или false.
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Давайте разберём программу по строкам:
age >= 18спрашивает «возраст не меньше 18?» — да, печатаетсяTrue.age == 18спрашивает «возраст ровно 18?» — нет, печатаетсяFalse.age != 18спрашивает «возраст не равен 18?» — да, печатаетсяTrue.- Результат сравнения можно положить в переменную типа
bool, как любое другое значение.
В коде значения пишут с маленькой буквы, true и false, а Console.WriteLine печатает их с большой: True и False.
Операторы сравнения
C# умеет задавать шесть вопросов:
==— равно;!=— не равно;<— меньше;>— больше;<=— меньше или равно;>=— больше или равно.
Сравнение выполняется после арифметики: в age + 1 >= 18 сначала считается age + 1.
Знак равенства в сравнении двойной. Одиночный = — это присваивание. Путать их — частая ошибка, о ней в конце урока.
Логические операторы
Часто одного вопроса мало. На этот фильм пускают, только если зрителю есть 18 и у него есть билет. Соединять такие вопросы помогают логические операторы:
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 на ноль — ошибка: программа на ней останавливается. Благодаря короткому замыканию левая часть может защищать правую от такой ошибки:
int count = 0;
int total = 10;
Console.WriteLine(count > 0 && total / count > 2); // False
Console.WriteLine(count == 0 || total / count > 2); // TrueДавайте посмотрим, почему программа не останавливается:
count > 0равноfalse, и&&не вычисляетtotal / count. Деления на ноль нет, и строка печатаетFalse.count == 0равноtrue, и||тоже не доходит до деления. Строка печатаетTrue.
Здесь аналогия с контролёром расходится с C#. Контролёр может начать с любого вопроса, а C# всегда вычисляет сначала левую часть, поэтому порядок частей важен. Если написать total / count > 2 && count > 0, деление выполнится раньше проверки, и программа остановится с ошибкой DivideByZeroException.
Короткое замыкание — частый вопрос на собеседовании. Ещё спрашивают, чем && отличается от &. С bool оператор & тоже означает «и», но всегда вычисляет обе части, поэтому count > 0 & total / count > 2 остановит программу той же ошибкой.
Частая ошибка
Вместо сравнения написали присваивание — один знак = вместо двух:
int age = 20;
bool isEighteen = age = 18; // ✗
Console.WriteLine(isEighteen);error CS0029: Cannot implicitly convert type 'int' to 'bool'Программа не компилируется. age = 18 кладёт 18 в age, и значение всего выражения — число 18. Положить число в переменную типа bool нельзя. Для сравнения нужны два знака: bool isEighteen = age == 18;.
Главное
- Операторы
==,!=,<,>,<=и>=сравнивают значения и даютbool:trueилиfalse. &&истинно, когда истинны обе части,||— когда истинна хотя бы одна, а!переворачивает значение.&&и||не вычисляют правую часть, если ответ ясен по левой.- Одиночный
=присваивает, двойной==сравнивает.