【问题标题】:why are assignments in conditions bad?为什么条件不好的作业?
【发布时间】:2010-09-23 22:53:49
【问题描述】:

我正在使用用于 PHP 6.5 的 NetBeans。

在我的代码中,我经常使用以下类型的命令:

if (($row = $db->get_row($sql))) {
        return $row->folder;
    } else {
        return FALSE;
    }

Netbeans 告诉我,我不应该在 IF 语句中使用赋值。

为什么?

【问题讨论】:

  • 我原以为双括号(赋值周围的括号)应该表明赋值是有意的。我认为在这种情况下,一些编译器会抑制警告。
  • 查看马克的回答:stackoverflow.com/a/2576969/560287
  • 关闭该警告,替换为测试驱动开发。 ;) === 之间的行为差​​异如此之大,您的测试应该会失败。 (不像 ===== - 我希望我的 IDE 对此发出警告,最好)
  • @LeeKowalkowski 这与混淆 = 和 == 无关。这与条件中的分配有关。例如,是否应该将 '$row = $db->get_row($sql)' 放在前一行。
  • 其他人已经回答说,条件表达式中对 = 的警告与混淆 = 和 == 有关。我只是说,通过充分的测试,你甚至不需要警告,因为这样的错误非常严重,测试会发现它们。因此,如果您发现使用 2 条语句而不是 1 条语句很乏味,请忽略该警告,并继续按照您的示例编写代码。

标签: php coding-style


【解决方案1】:

条件通常包括短路运算符。所以,给出这个例子:

if ( a=func(x) && b=func(y) )
{
  // do this
}

这可能不是很明显,但第二次分配只有在第一次返回 >0 时才会发生,并且如果 func(y) 有您所期望的其他副作用,它们也不会发生。

简而言之,如果您知道自己在做什么并且了解副作用,那么它没有任何问题。但是,您必须考虑到在您离开时其他人可能会维护您的代码,而他们可能没有您那么有经验。

此外,未来的维护者可能会认为您的意图如下:

if ( a==func(x) && b==func(y) ) ...

如果他们“修复”您的代码,他们实际上会破坏它。

【讨论】:

  • 我认为这应该对任何称职的程序员来说都是显而易见的。可能是我太苛刻了。
  • 是的,但是当你在调试时,类似的东西可以“混入”而不是立即跳出来,因此需要打破赋值操作的论点。
  • @Kip 是的,我 100% 同意你的看法。问题不是所有的程序员都物有所值。我们应该为我们的客户创建可维护的软件。做一个最低公分母的开发者可以维护的软件是不可能的,但我们至少可以做出一些让步。
  • 你仍然可以让它更具可读性:result = func(x) && b=func(y); if(result) ...
【解决方案2】:

如果您不在循环条件中分配 $row 值,代码会是什么样子 我认为这会复杂得多...... 虽然对于某些维护者来说不是那么好阅读,不是吗? 好吧,你可以这样做

$next = mysql_fetch_assoc($result)
do{
...
...
...

$next = mysql_fetch_assoc($result) or break;
}while ($next)

【讨论】:

  • 这肯定更具可读性:[对不起,cmets AFAIK 中没有换行符]。 while(true) { $next = mysql_fetch_assoc($result); if ( ! $next ) { break; } /* body here */ }
【解决方案3】:

我一直使用它们,带有循环(不知道为什么会有所不同),例如:

$counter = 0;
while( $getWhateverDataObj = mysql_fetch_object( $sqlResult )) {
   $getWhateverObj->firstName[$counter] = $getWhateverDataObj->firstName;
   $getWhateverObj->lastName[$counter]  = $getWhateverDataObj->lastName;
   $counter++;
}

而且效果很好。

【讨论】:

    【解决方案4】:

    在总是在赋值时返回值的语言中,它并不是(我认为这在函数式语言中很常见),但是(正如其他人在我输入这个时已经说过的那样)通常应该避免因为您或其他人可能会将其误认为是比较。编译器通常应该警告它,但如果你确定你在做什么,它可以被忽略......

    【讨论】:

      【解决方案5】:

      它们还不错,但它们可能会导致危险的错误。

      在类似 c 的语言中,赋值是一个表达式,(例如支持 a=b=c=1;)一个常见错误是:

      if (a = 1) { .. }
      

      但你想拥有

      if (a == 1) { .. }
      

      一些开发者已经学会了打字

      if (1 == a) { .. }
      

      如果忘记了一个“=”,则创建一个错误。但我认为它并没有提高可读性。

      然而现代编译器,如果你写了,就会发出警告

      if (a = 1) { .. }
      

      我认为这是一个更好的解决方案。在这种情况下,您必须检查这是否是您真正的意思。

      【讨论】:

      • 我相信用括号括起来的 if 中的赋值应该告诉编译器编码器知道他在做什么,他不应该被警告。
      • @strager 我仍然认为这是一种不好的做法,因为如果您在 if 子句中分配某些内容,它并不能真正提高可读性。你在一个命令中做两件事,这可能会导致误解,应该避免。
      • @strager 我之前已经多次犯了这个确切的错字,并让编译器抓住了我,这可以节省数小时的调试时间,具体取决于副作用何时出现(即是否编译时错误vs 向用户显示不正确的数据)
      • 非常糟糕! if (a=1 or b=1)... 无法知道第二个赋值是否执行。
      • 对于大多数语言,如果需要,您确实应该使用严格比较 (===) 和显式转换,这样就更难错过了。如果你真的想避免这样的错别字,你是否也应该避免在赋值中使用按位与(&)? (而且这个名单还可以继续……)
      【解决方案6】:

      它可能试图帮助您避免可怕的错字:

      if(a = b)
         //logic error
      

      虽然我希望环境足够聪明,可以警告你,但也足够聪明,可以有“哦,别担心那种情况”的条件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-12
        • 2020-08-14
        • 1970-01-01
        • 1970-01-01
        • 2018-07-21
        相关资源
        最近更新 更多