格式化带有多个条件的if语句的最佳方法


88

如果要基于两个或多个条件执行某些代码,这是格式化if语句的最佳方法?

第一个例子:

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

第二个例子:

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

请记住,每个条件可能是一个长函数名称或其他名称,因此最容易理解和阅读。


遗憾的是,此页面上没有人提及子字符串“ fast”或“ performance”。我就是来这里学习的。
Dreamspace总裁,

Answers:


132

我更喜欢选项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 ;)
}

恕我直言,选择“ B”的唯一原因是,如果您else要针对每种情况运行单独的功能。

例如

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

我喜欢。尽管我不是方法思想的忠实拥护者,除非方法已经存在并返回布尔值。
Thomas Owens

2
在第二个示例中,您是否没有理由就对所有内容进行了评估?
奥德斯

我会在条件之前使用“ &&”。很难使条件具有与示例中相同的字符长度。
Darkov

28

其他答案解释了为什么第一个选择通常是最好的。但是,如果您有多个条件,请考虑创建一个单独的函数(或属性),以在选项1中进行条件检查。这使代码更易于阅读,至少在使用良好的方法名称时更是如此。

if(MyChecksAreOk()) { Code to execute }

...

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

如果条件仅依赖于局部范围变量,则可以使新函数静态并传递所需的一切。如果有混合,请传入本地内容。


2
我发现这是最有效
且更

首先我+1了一下,但这确实是最好的答案,恕我直言。将布尔值isOkToDoWhatever作为属性非常有意义。
格林威治时间

1
但这只是将相同的复杂条件移到了其他地方,也需要使其易于理解,因此我们将对此重新归一。这不仅与if语句的可读性有关,还与条件的可读性有关。
罗伯特·科里特尼克'16

@RobertKoritnik我理解您在说什么,但我不认为我们会回到正题,因为我们降低了读者一口气需要考虑的复杂性。她可以查看条件,也可以使用条件具有(希望)好的名称的条件查看代码。至少我经常觉得这更容易理解,但是有时将所有细节都集中在一个地方也很不错。与往常一样,这取决于。
Torbjørn

利用好的方法名称和逻辑重构的重点。
JB Lovell

10

第一个例子更“容易阅读”。

实际上,我认为,仅在必须添加一些“其他逻辑”时才应使用第二种,但是对于简单的“条件”,请使用第一种。如果您担心这种情况的长久存在,则始终可以使用以下语法:

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

祝好运!


9

有人问过这个问题,到目前为止,已经回答了这个问题,好像该决定纯粹是基于“句法”的理由而作出的。

我要说的是,如何在假设条件下布置一些条件的正确答案应该取决于“语义”。因此,应该根据“概念上”组合在一起的条件分解条件并将其分组。

如果两个测试确实是同一枚硬币的两个侧面,例如。如果(x> 0)&&(x <= 100),则将它们放在同一行上。如果另一个条件在概念上距离更远,例如。user.hasPermission(Admin())然后放在自己的行上

例如。

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

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

以这种方式在if-else语句中格式化多个条件表达式:

  1. 允许以增强可读性:
    一。首先显示的表达式中的所有二进制逻辑运算{&&,||}
    。每个二进制操作的两个条件操作数都是显而易见的,因为它们垂直对齐
    c。使用缩进可以使嵌套的逻辑表达式操作变得显而易见,就像子句中的嵌套语句一样
  2. 需要显式括号(不依赖运算符优先级规则)
    一个。这样可以避免常见的静态分析错误
  3. 可以更容易调试
    一个。仅使用//
    b 禁用单个的单个条件测试。在任何单独的测试
    桶之前或之后设置一个断点...
// 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
{
   ... ;
}

这是我的方法。我唯一的问题是我还没有找到一个提供此选项的代码美化程序
Speed8ump


3

第一个比较容易,因为如果您从左到右阅读它,则会得到:“ If something AND someelse AND somethingelse THEN”,这是一个易于理解的句子。第二个示例显示为“如果某事则话,如果某事则话,如果其他则是话”,这很笨拙。

另外,请考虑是否要在子句中使用某些OR-如何在第二种样式中使用呢?


1

我相信,switch...case在这种情况下,如果编程语言支持的话,声明是编写整洁代码的最佳方法。

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

可能不错,但是它消除了“短路” /惰性评估的“优势”。
TheLibrarian '17

这个答案是完全错误的,实际上是危险的。问题是关于合取条件。switch语句仅是析取条件的解决方案。
egyik

0

在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
}

如果任何条件失败,它将在块之后继续。如果要定义任何要在块之后保留的变量,则需要在块之前定义它们。


1
看起来很不错-在“它做什么?”中 感觉;)但是,一旦您习惯了它,它实际上是可读的。
Piskvor于

-2

我已经面临这种困境很长时间了,但仍然找不到合适的解决方案。在我看来,唯一的好方法是先尝试摆脱条件,然后再突然比较5个条件。

如果没有其他选择,那么就像其他人建议的那样-将其分解为多个单独的名字,并缩短名称或将它们分组,例如,如果所有条件都必须为true,则使用诸如“如果x数组中没有false则运行”的名称。

如果一切失败,@ Eoin Campbell给出了很好的主意。


这不会在现有答案中添加任何新内容。
jerney

-4

当条件真的很复杂时,我使用以下样式(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
        )
    )
)

我相信它比嵌套多个级别的API更美观,更易读if()。在这种情况下,您根本无法将复杂的条件分解成碎片,因为否则您将不得不在if() {...}块中重复多次相同的语句。

我还认为,在代码中添加一些“空白”始终是一个好主意。它大大提高了可读性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.