Menu

if else в C#: цепочки else if, условия и частые ошибки

Как работают if, else if и else в C#: почему условия должны быть типа bool, объединение проверок через &&, || и !, когда важны фигурные скобки, ранний выход вместо глубокой вложенности, ошибки = вместо == и лишней точки с запятой.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Оператор if выполняет блок кода, только когда условие истинно. else if добавляет новые проверки, а else перехватывает всё, что не прошло проверки.

Вывод:

Order 120: shipping 0
Order 75.50: shipping 4.99
Order 20: shipping 9.99

Условия проверяются сверху вниз, и побеждает первое истинное. Заказ на 120 подходит под >= 100 и никогда не доходит до проверки >= 50, поэтому самое конкретное условие идёт первым. else if не отдельное ключевое слово: это else, телом которого является ещё один if, поэтому в C# нет ни elseif, ни elif.

Условия должны быть типа bool

C# никогда не считает число, строку или объект истинными или ложными. Выражение в скобках должно иметь тип bool:

int count = 3;
if (count)          // error CS0029: Cannot implicitly convert type 'int' to 'bool'
if (count > 0)      // correct
if (name)           // error: a string is not a bool either
if (name != null)   // correct

Это убирает целое семейство ошибок из C и JavaScript, где 0, "" и null молча считаются ложными. Цена в том, что сравнение приходится выписывать каждый раз, зато намерение видно следующему читателю.

Объединение условий через &&, || и !

&& (и), || (или) и ! (не) объединяют логические проверки. && и || работают по короткой схеме: правая часть выполняется, только если левая ещё не определила ответ.

Вывод:

maya: welcome
invalid or banned account
invalid or banned account
omar: age 9 rejected
invalid or banned account

Вызов с null безопасен благодаря короткой схеме: как только username != null оказывается ложным, username.Length не вычисляется, поэтому NullReferenceException не возникает. Поменяйте порядок на username.Length >= 3 && username != null, и тот же вызов упадёт.

&& связывает сильнее, чем ||, поэтому a || b && c означает a || (b && c). Ставьте скобки всякий раз, когда смешиваете их; компилятору они не нужны, а читателям нужны. Одиночные & и | тоже работают с bool, но всегда вычисляют обе части. Используйте их, только когда у правой части есть побочный эффект, который обязательно должен произойти.

Фигурные скобки и правило одного оператора

Если в ветке один оператор, скобки необязательны. Без них к if относится только следующий оператор, что бы ни говорил отступ:

Вывод:

Reorder email sent
Stock: 12

«Reorder email sent» печатается, хотя товара достаточно: второй WriteLine находится вне if, несмотря на отступ. Однострочная проверка вроде if (x == null) return; нормальна и без скобок; всё, у чего может появиться вторая строка, должно их получить.

Родственная ошибка это точка с запятой сразу после условия. if (stock < 5); завершает if пустым оператором, и следующий блок выполняется безусловно. Компилятор отмечает это предупреждением CS0642, Possible mistaken empty statement, которое стоит считать ошибкой.

= и == в условии

= присваивает, == сравнивает. Для большинства типов ошибочное = не компилируется, потому что результат присваивания это присвоенное значение, а int не является bool:

int score = 10;
if (score = 100) { }   // error CS0029: Cannot implicitly convert type 'int' to 'bool'

С переменной bool присваивание само имеет тип bool, поэтому опечатка компилируется:

Вывод:

Access granted
isAdmin is now True

Условие перезаписало isAdmin, а затем проверило новое значение. Компилятор предупреждает (CS0665, присваивание в условном выражении всегда даёт константу), но сборка всё равно проходит. Для bool вообще не пишите сравнение: if (isAdmin) и if (!isAdmin) читаются лучше, и в них такую опечатку не сделать.

Вложенные if и ранний выход

Каждый уровень вложенности это ещё одно условие, которое читатель должен держать в голове. Когда каждая проверка отсекает плохие входные данные, выходите раньше, вместо того чтобы вкладывать основной путь внутрь всех проверок:

Вывод:

ordered 2 x keyboard
error: no product
error: quantity must be positive
error: insufficient balance

Вложенная версия того же метода содержала бы три уровня if с настоящей работой в самом внутреннем блоке и три ветки else, разворачивающиеся внизу. С ранним выходом (guard clauses) каждое правило стоит рядом со своим сообщением об ошибке, а последняя строка это обычный случай. Та же идея работает внутри циклов с continue.

Объявление переменных в условии

Условие может объявить переменную, которая видна внутри if. Две распространённые формы: out var из метода TryParse и шаблон типа is:

Вывод:

42: positive number 42
abc: not a number
-7: number -7, not positive
string of length 5

TryParse возвращает false вместо исключения при плохом вводе, поэтому естественно подходит для if. Методы разбора подробно описаны на странице преобразование типов.

Когда использовать что-то другое

  • Выбор одного из двух значений: условный оператор condition ? a : b короче, чем if, присваивающий в обеих ветках.
  • Много веток по одному значению: оператор switch сравнивает значение с константными вариантами, и его легче просматривать, чем десять строк else if.
  • Сопоставление значения с результатом: поиск в Dictionary заменяет длинную цепочку, когда ветки различаются только данными.

Часто задаваемые вопросы

Как написать else if в C#?

Пишите else if двумя словами: if (a) { ... } else if (b) { ... } else { ... }. Условия проверяются сверху вниз, и выполняется только первая истинная ветка, поэтому самую конкретную проверку ставьте первой. Ключевых слов elif или elseif нет.

Почему в C# нельзя написать if (count)?

Условие в C# должно иметь тип bool. В отличие от C и JavaScript, int, строка или объект никогда не преобразуются в true или false, поэтому if (count) завершается ошибкой CS0029, Cannot implicitly convert type 'int' to 'bool'. Напишите проверку, которую имеете в виду: if (count > 0) или if (name != null).

Чем && отличается от & в условии if?

&& работает по короткой схеме: если левая часть ложна, правая никогда не вычисляется, и именно это делает s != null && s.Length > 0 безопасным. & для двух bool каждый раз вычисляет обе части. То же относится к || и |. Используйте в условиях && и ||, если вам не нужен побочный эффект правой части.

Обязательны ли фигурные скобки в операторе if в C#?

Нет. Без скобок if управляет ровно одним оператором. Отступ перед второй строкой не добавляет её в ветку, и это классический источник ошибок, поэтому большинство руководств по стилю рекомендуют ставить скобки в каждой ветке.

Можно ли написать if else в одну строку в C#?

Для выбора значения используйте условный оператор: string label = score >= 50 ? "pass" : "fail";. Для выполнения операторов запись if (x) DoA(); else DoB(); в одну строку допустима, но её труднее читать и расширять, чем блок в фигурных скобках.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ