循环中的条件,最佳实践

Conditions in loops, best practices?

本文关键字:最佳 条件 循环      更新时间:2023-10-16

假设我有一个这样的循环:

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

Versus。。。

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

有什么理由使用其中一个而不是另一个吗?还是仅仅是个人喜好
我想要的主要语言是Java,但我想它也适用于大多数其他语言。

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

我更喜欢第二个构造。。。

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

假设您在continue之前有很多代码。只要看一下就很明显

   else
    {
        doSomeOtherStuff();
    }

它不是无条件执行

对我来说,这取决于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
}

与。

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

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

尽可能避免继续语句。它使代码路径更难遵循,因此很难调试

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

只是给你一个参考:

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

不得使用continue语句。

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

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

http://www.jsf.mil/downloads/documents/JSF_AV_C++_编码标准_修订_C.doc

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

在这种特殊情况下,我同意其他人的看法,认为第二种更可取。但在某些情况下,我会选择第一个。如果DoSomething()实际上只是一个调用,而i == someCondition是一个边缘情况,并且doSomeOtherStuff()实际上是20行代码,而不仅仅是一个调用的话,那么我更喜欢使用continue。在那个场景中,我把它读成"首先,让我们快速处理这个边缘案例。好吧,现在让我们做真正的事情。"

当然,人们可以通过将我的解释改写为"如果我们处于边缘情况,就这样做,否则就做真正的事情"来为if-else辩护。但这意味着所有这20行现在都嵌套得更深,对我来说,先处理边缘情况,然后关注公共路径更容易阅读。

我确实相信有一个相关的理由更喜欢第一个而不是第二个,尽管在大多数情况下,第二个显然更可读

举个例子,你有很多,我的意思是循环中有很多条件,其中有很多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;
   }
   //...........  
}

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

这是一个简单的例子,但作为一个规则,如果有一个条件我正在从其他循环逻辑中"提取",我会通过continue尽快将其提取出来,而不是增加未来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();
}