Оператор 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(); в одну строку допустима, но её труднее читать и расширять, чем блок в фигурных скобках.