【问题标题】:How do I get rid of this goto?我该如何摆脱这个goto?
【发布时间】:2016-01-06 00:44:53
【问题描述】:

我刚开始一个职位,在工作日结束时,我通过慢慢阅读我们的代码库来等待流量。我遇到了这一点,即使在白板上花了相当长的时间后,我仍然想不出提取goto 的方法。有没有办法消除这种跳跃?

public void MyUpdate(MyType foo)
{
    /*Prep code for the loops*/        
    foreach (Thing bar in something)
    {
        foreach (Collection item in bar.Stuff)
        {
            Data dataRX = item.First;
            if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
            {
                // Update Data with the latest changes
                dataRX.fooBuddy = foo;
                goto exitLoops;
            }
        }
    }

    exitLoops: ;
}

【问题讨论】:

  • 如果exitLoops 在方法的末尾,为什么不return
  • @YacoubMassad 好主意,但在某些编码标准中,returning 在函数中的多个位置被认为是错误的形式,例如 goto。
  • 我更喜欢return 解决方案。提到的代码标准也不像我的回答那样喜欢breaks。但我认为这些标准通常是非常理论化的,在这种情况下不要认真。

标签: c# foreach refactoring goto


【解决方案1】:

由于标签exitLoops在方法的末尾,那么你可以简单地使用return这样退出方法:

if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
{
    // Update Data with the latest changes
    dataRX.fooBuddy = foo;
    return;
}

另一种方法是使用这样的标志:

bool done = false;

foreach (Thing bar in something)
{
    foreach (Collection item in bar.Stuff)
    {
        Data dataRX = item.First;
        if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
        {
            // Update Data with the latest changes
            dataRX.fooBuddy = foo;
            done = true;
            break;
        }
    }

    if(done)
        break;
}

即使标签后面有一些代码,您也可以使用第二种方法。

【讨论】:

  • 既然您指出了这一点,return-ing 似乎很明显。 exitLoops 标签之后曾经有很多空白,我敢打赌,这个函数中曾经有更多的代码。谢谢。
【解决方案2】:

将内部循环移动到方法中,并根据其返回值有条件地中断。

【讨论】:

    【解决方案3】:

    这不是很好,但是如果没有实现一个完整的新算法,这似乎是最简单的方法:

    foreach (Thing bar in something)
    {
        bool exitLoop = false;
        foreach (Collection item in bar.Stuff)
        {
            Data dataRX = item.First;
            if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
            {
                // Update Data with the latest changes
                dataRX.fooBuddy = foo;
                exitLoop = true;
                break;
            }
        }
    
        if (exitLoop) break;
    }
    

    【讨论】:

      【解决方案4】:

      或者,您可以使用 LINQ 执行此操作:

      public void MyUpdate(MyType foo)
      {
          Thing dummy = something.FirstOrDefault(bar => bar.Stuff.SkipWhile((item) => 
          {
              Data dataRx = item.First;
              if (dataRx != null && dataRx.ID.Equals(globalNonsense.ID))
              {
                  dataRx.fooBuddy = foo;
                  return false;
              }
              else
              {
                  return true;
              }
          }).Count() != 0);
      }
      

      【讨论】:

        【解决方案5】:

        如果您使用foreach,则需要breakreturn。但如果没有breakreturngoto,则有此选项:

        public void MyUpdate(MyType foo)
        {
            bool stop = false;
        
            /*Prep code for the loops*/        
            for (var i = 0; !stop && (i < something.Count); i++)
            {
                for (var j = 0; !stop && (j < something[i].Stuff.Count); j++)
                {
                    Data dataRX = something[i].Stuff[j].First;
                    if (dataRX != null && dataRX.ID.Equals(globalNonsense.ID))
                    {
                        // Update Data with the latest changes
                        dataRX.fooBuddy = foo;
                        stop = true;
                    }
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-09-27
          • 2013-07-19
          • 1970-01-01
          • 2021-07-07
          • 1970-01-01
          • 2019-01-15
          • 2021-09-28
          • 1970-01-01
          相关资源
          最近更新 更多