Лучший способ форматировать оператор с несколькими условиями

Если вы хотите, чтобы какой-то код выполнялся на основе двух или более условий, которые являются наилучшим способом форматирования этого оператора if?

первый пример: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Второй пример: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

который проще всего понять и прочитать, учитывая, что каждое условие может быть длинным именем функции или чем-то.

Ответ 1

Я предпочитаю вариант A

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
}

Ответ 2

Другие ответы объясняют, почему первый вариант, как правило, лучший. Но если у вас есть несколько условий, подумайте о создании отдельной функции (или свойства), выполняющей проверки условий в опции 1. Это делает код намного легче читать, по крайней мере, когда вы используете хорошие имена методов.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Это условия полагаются только на локальные переменные области, вы можете сделать старую новую функцию и передать все, что вам нужно. Если есть смесь, перейдите в локальный материал.

Ответ 3

Первый пример более "легко читается".

Собственно, по-моему, вы должны использовать только второй, когда вам нужно добавить какую-то "логику else", но для простого условного используйте первый вкус. Если вас беспокоит долгое условие, вы всегда можете использовать следующий синтаксис:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

Удачи!

Ответ 4

Вопрос был задан и до сих пор был дан ответ, как будто решение должно приниматься исключительно на "синтаксических" основаниях.

Я бы сказал, что правильный ответ на то, как вы выкладываете ряд условий в пределах if, должен также зависеть от "семантики". Таким образом, условия должны быть разбиты и сгруппированы в соответствии с тем, что происходит вместе "концептуально".

Если два теста действительно две стороны одной и той же монеты, например. если (x > 0) && (x <= 100) затем помещают их вместе в одну и ту же строку. Если другое условие концептуально гораздо более отдаленное, например. user.hasPermission(Admin()), затем поместите его на собственную строку

Eg.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}

Ответ 5

Второй - классический пример Arrow Anti-pattern Поэтому я бы избегал этого...

Если ваши условия слишком длинные, извлеките их в методы/свойства.

Ответ 6

    if (   ( single conditional expression A )
        && ( single conditional expression B )
        && ( single conditional expression C )
       )
    {
       opAllABC();
    }
    else
    {
       opNoneABC();
    }

Formatting a multiple conditional expressions in an if-else statement this way:
1) allows for enhanced readability:
    a) all binary logical operations {&&, ||} in the expression shown
       first
    b) both conditional operands of each binary operation are obvious
       because they align vertically
    c) nested logical expressions operations are made obvious using
       indentation, just like nesting statements inside clause
2) requires explicit parenthesis (not rely on operator precedence rules)
    a) this avoids a common static analysis errors
3) allows for easier debugging
    a) disable individual single conditional tests with just a //
    b) set a break point just before or after any individual test
    c) e.g. ...

    // 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
    {
       ... ;
    }

Ответ 7

Первый из них проще, потому что, если вы читаете его слева направо, вы получаете: "Если что-то И что-то и что-то еще", что легко понять. Второй пример гласит: "Если что-то ТОГДА, если что-то ТОГДА, если что-то еще ТЕМ", что неудобно.

Также подумайте, хотите ли вы использовать некоторые ORs в своем предложении - как вы это сделаете во втором стиле?

Ответ 8

Я считаю, что утверждение switch...case - лучший способ написать код в этом случае, если язык программирования поддерживает его.

switch (//variable or Boolean) {
  case //Condition A:
  case //Condition B:
  case //Condition C:
    //Code to execute;
}

Ответ 9

В Perl вы можете сделать это:

{
  ( 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
}

Если какое-либо из условий завершится неудачно, оно будет продолжено после блока. Если вы определяете любые переменные, которые хотите сохранить после блока, вам нужно будет определить их перед блоком.

Ответ 10

Когда условие действительно сложное, я использую следующий стиль (пример реальной жизни 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() {...} много раз.

Я также считаю, что добавление некоторого "воздуха" в код всегда является хорошей идеей. Это значительно улучшает читаемость.

Ответ 11

Я думаю, что в C вы не можете просто написать:

if ( variable = (1 || 2 || 3) ) {
    do stuff;
}

Или, может быть, лучше использовать инструкцию switch?