【问题标题】:Should I leave an unreachable break in a case where I throw an exception?在抛出异常的情况下,我应该留下一个无法访问的中断吗?
【发布时间】:2012-03-29 21:54:39
【问题描述】:

在无论如何都会抛出异常的情况下留下无法访问的中断语句是愚蠢的吗?如果逻辑发生变化,我的防御部分想把它留在那里。我的另一部分不希望其他开发人员在我的代码上看到编译器警告(“检测到无法访问的代码”)。

switch (someInt)
{
    case 1:
        // Do something
        break;
    case 2:
        // Do something else
        break;
    case 3:
        // Oh, we don't use threes here!
        throw new Exception("Business rules say don't use 3 anymore");
        break; // Unreachable...until the fickle business rules change...
    default:
        throw new Exception("Some default exception");
        break; // Unreachable...until...well, you get the idea.
}

怎么办?

更新

我看到一些回复说在以后删除抛出会导致编译器错误。但是,简单地删除(或评论)抛出而不在它之后中断会堆叠案例,这可能是意外行为。我并不是说这是一种可能的情况,但是……嗯,防御性编程是否只针对可能的情况?

【问题讨论】:

  • 不再需要break,我将其删除,因为我构建时将警告作为错误。
  • 有趣的问题 - 我最初的反应是包含 break 语句,但我认为这完全取决于习惯。
  • pragma warning 如果您认为您的担忧是有效的,但不想给他人带来不便,则禁用编译指示警告,但过度防御会很快使您的代码库变得混乱

标签: c# exception switch-statement break defensive-programming


【解决方案1】:

我会删除它们。几个原因:

  • 您目前不需要它们
  • 看到大量警告总是让我感到紧张,因为您可能会在来自这种类型警告的噪音中丢失真正的警告(假设您已将警告作为错误关闭)。

【讨论】:

  • 你怎么会错过“真正的错误”?要么您的代码无法编译,要么您已经确定警告不是“真正的错误”(即您没有使用“将警告视为错误”标志进行构建)。
  • 如果您在上面生成了 150 个警告,这些警告是噪音,并且您引入了一个生成有用警告的东西,那么很容易错过。
【解决方案2】:

我不会在switch 中“隐藏”它。我会尽快抛出ArgumentExceptions。这样可以避免副作用,也更透明。

有些人可能会在使用someInt 的开关前添加代码,尽管它是 3。

例如:

public void SomeMethod(int someInt)
{
    if (someInt == 3)
        throw new ArgumentException("someInt must not be 3", "someInt");

    switch (someInt)
    {
        // ...
    }
}

【讨论】:

    【解决方案3】:

    就个人而言,我绝不会在生产代码中留下无法访问的代码。它可以用于测试,但不要这样。

    你不会这样做吧?

    public void MyMethodThatThrows()
    {
        throw new Exception();
        return;  // unneeded
    }
    

    那么为什么要保留break

    【讨论】:

    • 我很理解这部分的第一部分,这是一个很好的观点。然而,这个例子有点像稻草人,因为虽然我不会在 void 中放置 return ,但我肯定会在 switch 中放置 break 。当然,这个问题是关于休息而不是在切换中返回的,因为,嗯,我是一个单一的退出类型的人。
    • @TimLehner,哈哈,好点子。我的例子基本上只是夸大了这个问题。
    【解决方案4】:

    通过忽略一些编译器警告,您正在强化忽略任何编译器警告的不良行为。在我看来,这比留下break 语句所获得的任何好处都要大。

    编辑:我删除了我原来的观点,即如果要删除 throw 语句,编译器会强制您将 break 语句放回原处。正如 payo 指出的那样,在某些情况下,编译器不会。它只会将案例与下面的案例结合起来。

    【讨论】:

    • 如果case没有其他代码(在注释throw之后),编译器不会强制你添加break。
    • 你是对的。在这种情况下,程序员有责任写出好的代码。
    【解决方案5】:

    我会删除它。

    它消除了警告,即使要更改逻辑并删除异常,您也会收到编译器错误,提示需要重新添加中断。

    【讨论】:

    • 其实有一种情况是我们都错了。如果异常被删除并且没有添加任何内容,则正文将为空并允许在没有警告或错误的情况下失败。
    【解决方案6】:

    我的防御部分想把它留在那里,以防万一 逻辑变化。

    这里究竟有什么逻辑可以改变?抛出异常时会发生什么记录得很好。而且我认为您可以合理地确定,以后对 C# 的修订不会对“迄今为止编写的所有程序都不再工作”造成重大变化。

    即使没有编译器警告,冗余代码也不是一件好事,除非在日常维护期间有可能通过防止错误来发挥代码的作用,在这种情况下,我们不能合理地说存在这种可能性.

    【讨论】:

    • 我认为他的意思是如果异常被删除,但即使这样也不是问题,因为你必须有一个或另一个。
    • 也许我在那里使用了错误的术语,但不,我不是说如果 C# 规范发生变化,只是变化无常的业务规则。
    【解决方案7】:

    我的防御性部分希望在逻辑发生变化时将其留在那里。

    好吧,如果您删除 throw 并忘记添加 break,编译器会通知您。

    我认为没有理由休息。这是多余的,无论如何你都会触发警告,所以我会删除它。没有充分的理由留下无用的代码来混乱你的逻辑。

    【讨论】:

    • 简单地移除没有休息的投掷会堆叠箱子,这可能是意想不到的行为。
    • @TimLehner:这是真的,因为身体是空的。也就是说......如果你让身体空着,那么我认为你这样做是有原因的。我希望您可以信任您的同事,了解开关的基本工作原理。
    • 我们不都希望同样的事情,真的吗? :)
    • @TimLehner:呵呵,是的,但老实说......会发生错误,这里没有白痴证明选项。如果您的开发人员经常犯愚蠢的错误……是时候寻找新员工了。
    • @payo:感谢您重申这一点。
    【解决方案8】:

    我希望我的项目资源如此酷且无故障,以至于我不得不考虑防御性编程的这种小案例 :)

    我的意思是在软件开发中存在太多的陷阱——COM 和互操作、安全/权限和身份验证、证书……天哪,无法告诉你我必须写多少代码保护自己免于脚部射击。

    只需删除此中断,因为它是多余的,对于那些知道“案例”应该以 breakreturn 结尾的人来说会感到困惑,并且对于不知道这一点的人来说应该是显而易见的。

    【讨论】:

    • 没错,这不是任何人生活中最大的问题。现在,以回报告终的案件绝对有待商榷……
    【解决方案9】:

    MSDN C# Reference 声明:“每个 case 块之后都需要一个跳转语句,例如 break,包括最后一个块,无论它是 case 语句还是默认语句。”

    那么,“抛出”不构成“跳转语句”吗?我认为确实如此。因此,“中断”不是必需的,“无法访问”的问题就消失了。 :)

    【讨论】:

    • OP 承认 breaks 不是必需的,但正在考虑将它们留在防守端。考虑一下如果你决定做一些事情而不是抛出异常会发生什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 2015-05-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多