循环中的条件,最佳实践?

时间:2012-01-17 15:46:57

标签: java c++ loops coding-style

说我有这样的循环:

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
        continue;
    }
    doSomeOtherStuff();
}

...对战

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
    }
    else
    {
        doSomeOtherStuff();
    }
}

有没有理由使用一个而不是另一个?或者只是个人偏好? 我要求的主要语言是Java,但我想它也适用于大多数其他语言。

8 个答案:

答案 0 :(得分:16)

技术上,不,但我发现第二个更适合这种特殊情况。

答案 1 :(得分:7)

我更喜欢第二种结构...

for (int i = 0; i < someint; i++)
{
    if (i == somecondition)
    {
        DoSomething();
        //lets say lot of code
        //..
        //...
        //...
        //...
        continue;
    }
    else
    {
        doSomeOtherStuff();
    }
}

假设你在continue之前有很多代码。通过查看

立即显现出来
   else
    {
        doSomeOtherStuff();
    }

不是无条件执行

答案 2 :(得分:5)

对我而言,这取决于thenelse分支相对大小之间的分歧:如果一个大于另一个,而较小的一个代表逻辑异常情况,我将较短的一个放入then,然后添加continue;当它们在大小和逻辑流程中大致相等时,我将它们保存在自己的thenelse分支中。

for (String tok : tokens) {
    if (isKeyword(tok)) {
         output.write(tok);
         continue;
    }
    // Do some massive processing of non-keyword tokens here
    // This block goes on...
    // and on...
    // and on... You get the idea
}

VS

for (String op : operators) {
    if (isAdditive(op)) {
        // Do something for additive ops
    } else {
        // Do something for non-additive ops
    }
}

答案 3 :(得分:2)

我肯定更喜欢第二种语法。

尽可能避免使用continue语句。它使代码路径更难以遵循,因此难以调试

答案 4 :(得分:2)

正如大家所说,建议使用第二种形式。许多编码标准建议您避免使用“continue”和“break”语句,因为它会增加代码的复杂性。

只是给你一个参考:

JSF ++(规则190)和Misra C(规则57)说:

  

不得使用continue语句。

这些是安全关键应用程序的标准,但它们也可以应用于其他应用程序。

Misra已付款,但JSF ++可以在这里免费下载:

http://www.jsf.mil/downloads/documents/JSF_AV_C++_Coding_Standards_Rev_C.doc

适用于C ++,但许多规则可以应用于其他语言。值得一读!

答案 5 :(得分:1)

在这种特殊情况下,我同意其他所有人的意见,即第二种情况更可取。但有些情况下,我会选择第一个。如果DoSomething()真的只是那一个电话,i == someCondition是边缘情况,doSomeOtherStuff()实际上是20行代码,而不仅仅是那一个电话,那么我更喜欢使用continue。在那种情况下,我将其视为&#34;首先,让我们快速处理这个边缘案例。好的,现在让我们做真实的事情。&#34;

当然,人们可以通过将我的解释改为&#34来为if-else提出论证;如果我们在边缘案例中这样做,那么就做真实的事情。&#34;但这意味着所有这20条线现在更加嵌套,对我来说,首先处理边缘情况更加可读,然后专注于共同路径。

答案 6 :(得分:0)

我确实相信有一个相关的理由偏好第一个,第二个,虽然在大多数情况下,第二个是更具可读性

比如说你有很多,我的意思是你的循环中有很多很多条件,其中有很多if语句实际上会影响缩进的可读性:

for ( int i = 0 ; i < n ; i++ )
{
   if ( obj[i] )
   {
      doSomething();
      if ( someOtherCondition() 
      {
           //...........
                                                  if ( /* some levels down */ )
                                                  {

                                                  }
           //.....
      }  
   }
}

我可能会得到像“你可以重构它”的论点等等等等,但有时,很少,你根本就不能。

所以你可以通过以下方式重构并使其更具可读性:

for ( int i = 0 ; i < n ; i++ )
{
   if ( !obj[i] )
   {
       continue;
   }
   doSomething();
   if ( !someOtherCondition() 
   {
       continue;
   }
   //...........  
}

答案 7 :(得分:0)

我认为这更多地取决于你在做什么。

这是一个简单的例子,但是作为规则,如果我从其他循环逻辑中“提取”的条件,我将尽可能快地将其拉出来,而不是增加未来的复杂性if语句(你的第一个例子,如果它是一个可以提取的条件,简化了未来的逻辑)例如:

for ( int i = 0 ; i < n ; i++ )
{
    if( obj[i] != null && obj[i].instanceOf("A")) {
        doSomething();
    } else if(obj[i] != null && obj[i].instanceOf("B"){
        doSomethingElse();
    }
}

现在很清楚将第一个条件提取到

if(obj[i] == null) {
    continue;
}

可以节省一些混乱,因为这个循环得到了增强。我使用这种策略来测试方法参数,并提前返回或抛出异常。

另外(这完全不是答案,完全不是答案的一部分!),我会说,如果你看到一个“真正”平衡的状态,你可能会认真考虑你的OO设计。如果doSomething和someOtherCondition类似,那么它们可能应该是基类或接口中定义的方法的不同实现,从而产生以下代码:

for ( int i = 0 ; i < n ; i++ )
{
    obj[i].doSomething();
}