Если вы хотите, чтобы какой-то код выполнялся на основе двух или более условий, как лучше всего отформатировать этот оператор if?
первый пример: -
if (ConditionOne && ConditionTwo && ConditionThree)
{
Code to execute
}
Второй пример: -
if (ConditionOne)
{
if (ConditionTwo )
{
if (ConditionThree)
{
Code to execute
}
}
}
что легче всего понять и прочитать, имея в виду, что каждое условие может быть длинным именем функции или чем-то еще.





Первый вариант проще, потому что, если вы читаете его слева направо, вы получите: «Если что-то И что-то другое И что-то еще ТО», это простое для понимания предложение. Второй пример гласит: «Если что-то ТО, если что-то еще ТО, если что-то еще ТО», что неуклюже.
Кроме того, подумайте, хотите ли вы использовать несколько операторов OR в своем предложении - как бы вы это сделали во втором стиле?
Другие ответы объясняют, почему обычно лучше всего первый вариант. Но если у вас несколько условий, подумайте о создании отдельной функции (или свойства), выполняющей проверку условий в варианте 1. Это значительно упрощает чтение кода, по крайней мере, когда вы используете правильные имена методов.
if (MyChecksAreOk()) { Code to execute }
...
private bool MyChecksAreOk()
{
return ConditionOne && ConditionTwo && ConditionThree;
}
Если условия зависят только от переменных локальной области видимости, вы можете сделать новую функцию статической и передать все, что вам нужно. Если есть микс, передайте местный материал.
Я обнаружил, что это наиболее эффективный и простой способ добавить условия позже.
+1 сначала я приподнял бровь но это действительно лучший ответ имхо. наличие этого логического isOkToDoWhatever в качестве свойства имеет большой смысл.
Но это просто перемещает то же сложное условие в другое место, где он также должен быть читабельным, так что мы вернулись к исходной точке с этим. Дело не только в удобочитаемости ifstatement, но и в удобочитаемости условий.
@RobertKoritnik Я понимаю, о чем вы говорите, но не думаю, что мы вернулись к исходной точке, потому что мы снизили сложность, которую читатель должен учитывать за один раз. Она может посмотреть на условия, ИЛИ она может посмотреть на код, используя условия, в которых условия имеют (надеюсь) красивое имя. По крайней мере, мне часто легче это понять, но, опять же, иногда приятно собрать все детали в одном месте. Как всегда, зависит от обстоятельств.
Отличный смысл использовать хорошие имена методов и рефакторинг логики.
Я предпочитаю вариант А
bool a, b, c;
if ( a && b && c )
{
//This is neat & readable
}
Если у вас есть особенно длинные переменные / условия метода, вы можете просто разорвать их на строку
if ( VeryLongConditionMethod(a) &&
VeryLongConditionMethod(b) &&
VeryLongConditionMethod(c))
{
//This is still readable
}
Если они еще более сложные, я бы подумал о том, чтобы делать методы условия отдельно, вне оператора if.
bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);
if ( aa && bb && cc)
{
//This is again neat & readable
//although you probably need to sanity check your method names ;)
}
IMHO Единственная причина для варианта «B» - это если у вас есть отдельные функции else, которые нужно запускать для каждого условия.
например
if ( a )
{
if ( b )
{
}
else
{
//Do Something Else B
}
}
else
{
//Do Something Else A
}
Мне это нравится. Хотя я не большой поклонник идеи метода, если только методы уже не существуют и не возвращают логическое значение.
Разве во втором примере вы не оцениваете все без причины?
Я бы использовал "&&" перед условием. Трудно иметь условия с такой же длиной символа, как в примере.
Первый пример более «читается».
На самом деле, на мой взгляд, вы должны использовать только второй вариант, когда вам нужно добавить некоторую «логику else», но для простого Conditional используйте первый вариант. Если вас беспокоит длина условия, вы всегда можете использовать следующий синтаксис:
if (ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
&& ConditionTwoThatIsLongAsWell
&& ConditionThreeThatAlsoIsLong) {
//Code to execute
}
Удачи!
Второй - классический пример Стрелка Анти-узор, поэтому я бы его избегал ...
Если ваши условия слишком длинные, извлеките их в методы / свойства.
Вопрос был задан и до сих пор получен ответ, как будто решение должно приниматься исключительно на «синтаксических» основаниях.
Я бы сказал, что правильный ответ о том, как вы выкладываете ряд условий в if, должен тоже зависит от «семантики». Таким образом, условия должны быть разбиты и сгруппированы в соответствии с тем, что «концептуально» сочетается.
Если два теста действительно являются двумя сторонами одной медали, например. если (x> 0) && (x <= 100), то поместите их в одну строку. Если другое условие концептуально гораздо более отдаленное, например. user.hasPermission (Admin ()), затем поместите его в отдельную строку
Например.
if user.hasPermission(Admin()) {
if (x >= 0) && (x < 100) {
// do something
}
}
{
( VeryLongCondition_1 ) or last;
( VeryLongCondition_2 ) or last;
( VeryLongCondition_3 ) or last;
( VeryLongCondition_4 ) or last;
( VeryLongCondition_5 ) or last;
( VeryLongCondition_6 ) or last;
# Guarded code goes here
}
Если какое-либо из условий не выполняется, он просто продолжится после блока. Если вы определяете какие-либо переменные, которые хотите сохранить после блока, вам нужно будет определить их до блока.
Вот и смотрит Перлиш - в графе "ЧТО делает?" смысл;) Но на самом деле он читается, как только вы к нему привыкнете.
Когда условие действительно сложное, я использую следующий стиль (пример из реальной жизни PHP):
if ( $format_bool &&
(
( isset( $column_info['native_type'] )
&& stripos( $column_info['native_type'], 'bool' ) !== false
)
|| ( isset( $column_info['driver:decl_type'] )
&& stripos( $column_info['driver:decl_type'], 'bool' ) !== false
)
|| ( isset( $column_info['pdo_type'] )
&& $column_info['pdo_type'] == PDO::PARAM_BOOL
)
)
)
Я считаю, что это более удобно и читабельно, чем вложение нескольких уровней if (). И в некоторых случаях, подобных этому, вы просто не можете разбить сложное условие на части, потому что в противном случае вам пришлось бы повторять одни и те же операторы в блоке if () {...} много раз.
Я также считаю, что добавление «воздуха» в код - всегда хорошая идея. Это значительно улучшает читаемость.
if ( ( single conditional expression A )
&& ( single conditional expression B )
&& ( single conditional expression C )
)
{
opAllABC();
}
else
{
opNoneABC();
}
Форматирование нескольких условных выражений в операторе if-else следующим образом:
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if ( 1
&& ( single conditional expression A )
&& ( single conditional expression B )
&& ( 0
|| ( single conditional expression C )
|| ( single conditional expression D )
)
)
{
... ;
}
else
{
... ;
}
Это мой метод. Единственная проблема, с которой я столкнулся, - мне еще предстоит найти средство для украшения кода, которое предлагает это в качестве опции.
Я столкнулся с этой дилеммой долгое время и до сих пор не могу найти правильного решения. На мой взгляд, единственный хороший способ - это сначала попытаться избавиться от состояний раньше, чтобы вы не сравнивали сразу 5 из них.
Если альтернативы нет, то, как предлагали другие, - разбейте ее на отдельные и сократите имена или сгруппируйте их и, например, если все должно быть истинным, используйте что-то вроде «если в массиве x нет false, то запустить».
Если ничего не получится, @Eoin Campbell высказал неплохие идеи.
Это не добавляет ничего нового к уже существующим ответам.
Жалко, что никто на этой странице не упоминает подстроку «быстро» или «производительность». Это то, что я пришел сюда, чтобы узнать.