Почему вы используете назначение в состоянии?


во многих языках назначения являются законными в условиях. Я никогда не понимал причину этого. Зачем тебе писать:

if (var1 = var2) {
  ...
}

вместо:

var1 = var2;
if (var1) {
  ...
}
11 62

11 ответов:

это более полезно для циклов, чем если операторы.

while( var = GetNext() )
{
  ...do something with var 
}

который в противном случае должен быть написан

var = GetNext();
while( var )
{
 ...do something
 var = GetNext();
}

это более полезно, если вы вызываете функцию:

if (n = foo())
{
    /* foo returned a non-zero value, do something with the return value */
} else {
    /* foo returned zero, do something else */
}

конечно, вы можете просто поставить n = foo(); на отдельном заявлении, то если (n), но я думаю, что выше довольно читаемая идиома.

Я нахожу его наиболее полезным в цепочках действий, которые часто включают обнаружение ошибок и т. д.

if ((rc = first_check(arg1, arg2)) != 0)
{
    report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
    report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
    report error based on new rc
}
else
{
    do what you really wanted to do
}

альтернативой (не используя назначение в условии) является:

rc = first_check(arg1, arg2);
if (rc != 0)
{
    report error based on rc
}
else
{
    rc = second_check(arg2, arg3);
    if (rc != 0)
    {
        report error based on new rc
    }
    else
    {
        rc = third_check(arg3, arg4);
        if (rc != 0)
        {
            report error based on new rc
        }
        else
        {
            do what you really wanted to do
        }
    }
}

при длительной проверке ошибок альтернатива может работать с RHS страницы, в то время как версия присваивания в условной версии этого не делает.

это может быть полезно, если вы вызываете функцию, которая возвращает данные для работы или флаг, чтобы указать на ошибку (или что вы сделали).

что-то типа:

while ((c = getchar()) != EOF) {
    // process the character
}

// end of file reached...

лично это идиома, которую я не очень люблю, но иногда альтернатива страшнее.

GCC может помочь вам обнаружить (с-Wall), если вы непреднамеренно пытаетесь использовать назначение в качестве значения истины, в случае, если он рекомендует вам написать

if ((n = foo())) {
   ...
}

т. е. использовать дополнительные скобки, чтобы указать, что это действительно то, что вы хотите.

идиома более полезна, когда вы пишете while петли вместо if заявление. Для if заявление, вы можете разбить его, как вы описываете. Но без этой конструкции вам либо придется повторить:

c = getchar();
while (c != EOF) {
    // ...
    c = getchar();
}

или использовать петлю с половиной структуру:

while (true) {
    c = getchar();
    if (c == EOF) break;
    // ...
}

Я обычно предпочитаю петлю с половиной формы.

в PHP, например, это полезно для циклического перебора результатов базы данных SQL:

while ($row = mysql_fetch_assoc($result)) {
    // Display row
}

это выглядит намного лучше, чем:

$row = mysql_fetch_assoc($result);
while ($row) {
    // Display row
    $row = mysql_fetch_assoc($result);
}

короткий ответ: Expression-oriented языки программирования позволяют более лаконичный код. Не заставляйте вас отделить команды от запросов.

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

while (checkstatus() != -1) {
    // process
}

, а

while (true) {
    int error = checkstatus();
    if (error != -1)
        // process
    else
        //fail
}

теперь во время одного шага мы можем узнать, что было возвращенным кодом ошибки из checkstatus().

if((var = someFunction())){ //Enclosed in additional pair of brackets to show its intentional
...

вышеуказанное можно использовать вместо...

var = someFunction();
if(var){
...

причина :

  1. улучшение производительности (иногда)

  2. Иной Код (Всегда)

возьмем пример: есть метод someMethod() и if условии, что вы хотите проверить, является ли возвращаемое значение метода null. Если нет, вы собираетесь использовать возвращаемое значение снова.

If(null != someMethod()){
    String s = someMethod();
    ......
    //Use s
}

это будет препятствовать производительности, так как вы вызываете один и тот же метод дважды. Вместо использование:

String s;
If(null != (s = someMethod())) {
    ......
    //Use s
}