【问题标题】:Best practice for using goto使用 goto 的最佳实践
【发布时间】:2011-03-30 10:21:24
【问题描述】:

在这段代码中使用goto 是否正确?有没有其他选择?

return ExecuteReader(cmd, reader =>
{
    List<BEPartnership> partnerhip = null;

    //Partnership
    if (!((SqlDataReader) reader).HasRows)
        goto exit;

    partnerhip = 
        new List<BEPartnership>{new BEPartnership().GetFromReader(reader)};

    //Customers
    if (!reader.NextResult() && !((SqlDataReader) reader).HasRows)
        goto exit;

    foreach (BEPartnership p in partnerhip)
        p.Partner = new BECustomer().GetFromReader(reader);

    //Contracts
    if (!reader.NextResult() && !((SqlDataReader) reader).HasRows)
        goto exit;

    List<BEContractB2B> contracts = new List<BEContractB2B>();
    contracts.Add(new BEContractB2B().GetFromReader(reader));
    // contracts = new BEContractB2B().GetFromReader2(reader).ToList();

    exit:
    return partnerhip;
});

【问题讨论】:

  • 最佳做法是:不要使用 GOTO!
  • @Steven:过于简单化了
  • 在某些情况下使用 goto 非常有用。
  • 有些情况下使用goto是很没用的。
  • @Mongus:每次创建循环时,编译器都会将 goto 放入已编译的 IL。 IL 只有三个基本的控制流程:throw、goto 和 return。几乎一切都是goto。结构化编程的重点是选择比 goto 更有意义的控制流,而不是完全避免分支。

标签: c# .net goto


【解决方案1】:

如果您希望返回当前填充的列表,您可以将每个 goto exit; 替换为 return null;return partnerhip;。 (我认为合作伙伴是很酷的合作伙伴?)

【讨论】:

    【解决方案2】:

    我会说不。

    我从 2001 年开始使用 C# 编程,从未使用过 goto!

    如果您想在代码中“短路”退出,为什么不替换

    goto exit:
    

    return partnership
    

    【讨论】:

    • 阿门。编写简短的函数,您将永远不需要goto
    【解决方案3】:

    goto 和“最佳实践”在我看来是相互排斥的(可能/希望在大多数其他人看来也是如此)。需要goto 表示代码设计错误。在您的情况下,解决方案似乎很简单:我认为您只需将goto exit 替换为return partnerhip 并删除标签exit:。 (应该写成“伙伴关系”而不是“伙伴关系”?)

    【讨论】:

      【解决方案4】:

      您最后要做的是从阅读器那里加载合同(如果有的话)。如果你用一个简单的 if 语句明确表达这个意图,它会更好读。

      把结尾改成:

      if (reader.NextResult() || ((SqlDataReader) reader).HasRows)
      {
          List<BEContractB2B> contracts = new List<BEContractB2B>();
          contracts.Add(new BEContractB2B().GetFromReader(reader));
      }
      
      return partnerhip;
      

      虽然看起来你只是忽略了合同列表......它没有做任何事情。除非创建一个新的 BEContractB2B 类有一些全局副作用(坏消息),否则你可以完全摆脱它..

      将第一个 goto 更改为

      if (!((SqlDataReader) reader).HasRows)
          return null;
      

      既然这就是你正在做的事情,你应该清楚地表明你将返回 null。

      【讨论】:

        【解决方案5】:

        我发现以下情况 goto 可能有点用处:When To Use Goto When Programming in C。但是“从不使用 GOTO”是我在大学里学到的第一件事,所以我真的从来没有使用过它(至少在 C、C++、C#、Java...中没有使用过)。

        GOTO 最大的问题是,如果你读一段方法,你看不到它从哪里被调用。例如:

        int a = 1;
        division:
        int b = 4 / a;
        

        ...听起来不错。但是你写的是 0-dividing crash,如果在除法块之后有下面的 GOTO:

        int a = 1;
        division:
        int b = 4 / a;
        // ... hundreds of lines ...
        a = 0;
        goto division;
        

        ...如果在分割块之前有GOTO,则空异常崩溃:

        goto division;
        // ... hundreds of lines ...
        int a = 1;
        division:
        int b = 4 / a;
        

        ...这只是一个例子,GOTO 会导致更多有争议的情况。所以请忘记 GOTO,人们(包括您)在阅读您的代码时会更开心。

        使用“回归伙伴关系”;而不是你的 goto。

        【讨论】:

        • 实际上,您的第二个示例甚至无法编译。首先,a 是一个值类型,不能永远null。其次,编译器会检测到int a = 1;不可达,首先发出代码不可达警告,然后使用未分配的局部变量错误,这将导致代码无法编译。
        猜你喜欢
        • 2012-12-31
        • 1970-01-01
        • 2017-11-29
        • 2010-10-08
        • 2012-04-11
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多