简体   繁体   English

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

[英]Conditions in loops, best practices?

Say I have a loop like this: 说我有这样的循环:

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();
    }
}

Is there any reason to use one over the other? 有没有理由使用一个而不是另一个? Or is it just personal preference? 或者只是个人偏好?
The main language I'm asking this for is Java, but I guess it also applies to most others. 我要求的主要语言是Java,但我想它也适用于大多数其他语言。

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

I prefer the second construct... 我更喜欢第二种结构......

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

Lets say you had lot of code before the continue . 让我们说在continue之前你有很多代码。 It is immediately apparent just by looking 通过观察,它立即显而易见

   else
    {
        doSomeOtherStuff();
    }

the it is not executed unconditionally . 它没有无条件执行

To me, this depends on what's the split between the then and the else branch relative sizes: if one is massively larger than the other, and the smaller one represents a logically exceptional situation, I put the shorter one into then , and add a continue ; 对我来说,这取决于thenelse分支相对大小之间的区别:如果一个大于另一个,并且较小的一个代表一个逻辑上异常的情况,我将较短的一个放入then ,并添加一个continue ; when they are roughly equal, both in size and in the logic flow, I keep them in their own then and else branches. 当他们大致相等,无论在规模和逻辑流,我让他们在自己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
    }
}

I would definitely prefer the second syntax. 我肯定更喜欢第二种语法。

Try to avoid continue statements wherever possible. 尽可能避免继续发表声明。 It makes the code path more difficult to follow and therefor difficult to debug 它使代码路径更难以遵循,因此难以调试

As everyone said, the second form is recommended. 正如大家所说,建议使用第二种形式。 Many coding standards recommend you to avoid "continue" and "break" statements because it adds complexity to your code. 许多编码标准建议您避免使用“continue”和“break”语句,因为它会增加代码的复杂性。

Just to give you a reference: 只是给你一个参考:

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

The continue statement shall not be used. 不得使用continue语句。

Those are standards for safety-critical applications, but they can be applied to other apps as well. 这些是安全关键应用程序的标准,但它们也可以应用于其他应用程序。

Misra is paid, but JSF++ can be downloaded for free here: Misra已付款,但JSF ++可以在这里免费下载:

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

It is for C++, but many rules can be applied to other languages. 它适用于C ++,但许多规则可以应用于其他语言。 It worths the reading! 值得一读!

In this particular case, I agree with everyone else that the second is preferable. 在这种特殊情况下,我同意其他所有人的观点,即第二种情况更可取。 But there are cases where I'd go for the first. 但有些情况下我会选择第一个。 If DoSomething() were really just that one call, and i == someCondition is an edge case, and doSomeOtherStuff() were actually 20 lines of code instead of just that one call, then I'd prefer using the continue . 如果DoSomething()实际上只是那个调用,并且i == someCondition是一个边缘情况,并且doSomeOtherStuff()实际上是20行代码而不是那一个调用,那么我更喜欢使用continue In that scenario, I read it as "first, let's take care of this one edge case quickly. Okay, now let's do the real stuff." 在那种情况下,我把它读作“首先,让我们快速处理这个边缘案例。好吧,现在让我们做真实的事情。”

Of course, one could make the argument for the if-else by rephrasing my interpretation to "if we're in the edge case do this, else do the real stuff." 当然,人们可以通过将我的解释改为“如果我们处于边缘情况下这样做,而不是做真实的东西”来为if-else做出论证。 But that means all those 20 lines are now one nesting deeper, and to me it's more readable to take care of the edge cases first, and then focus on the common path. 但这意味着所有这20行现在都是更深的嵌套,对我来说,首先处理边缘情况更加可读,然后专注于共同路径。

I actually do believe there is a pertinent reason to prefer the first over the second, although in most cases, the second is definetely more readable . 我确实相信有一个相关的理由偏好第一个, 而在大多数情况下,第二个是更具可读性

Say for example you have a lot, and I mean a lot of conditions inside your loop, where by having a lot of if statements actually affects readability through indentation: 比方说,你有很多,我的意思你的循环中有很多条件,其中有很多if语句实际上通过缩进影响可读性:

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

                                                  }
           //.....
      }  
   }
}

I might get arguments like "You can refactor it" blah blah, but sometimes , rarely, you simply can't. 我可能得到像“你可以重构它”的论点等等等等,但有时候很少,你根本就不能。

So you can refactor and make it a lot more readable with: 所以你可以重构并使它更具可读性:

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

I think it depends more on what you are doing. 我认为这更多地取决于你在做什么。

This is a simple example, but as a rule if there is a condition that I'm "Extracting" from other loop logic, I will pull it out as quickly as possible with a continue rather than adding to the complexity of future if statements (your first example IF it is a condition that can be extracted simplifying future logic) For instance: 这是一个简单的例子,但是作为规则,如果我从其他循环逻辑中“提取”一个条件,我会尽可能快地将其拉出来,而不是增加未来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();
    }
}

NOW it's clear that extracting the first condition into 现在很清楚将第一个条件提取到

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

could save some confusion as this loop gets enhanced. 这个循环得到增强,可以节省一些混乱。 I use this tactic a lot for testing method parameters and either returning early or throwing an exception. 我经常使用这种策略来测试方法参数,并提前返回或抛出异常。

Also (This is totally an aside, not part of the answer at all!), I'd say that if you ever see a "Truly" balanced condition you might give a serious thought to your OO design. 另外(这完全是一个旁边,根本不是答案的一部分!),我会说,如果你看到一个“真正”平衡的状态,你可能会认真考虑你的OO设计。 If doSomething and someOtherCondition were that similar, they should probably be different implementations of a method defined in a base class or interface, leading to this code: 如果doSomething和someOtherCondition类似,它们可能应该是基类或接口中定义的方法的不同实现,从而产生以下代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM