【问题标题】:Is it "bad" to use try-catch for flow control in .NET?在 .NET 中使用 try-catch 进行流控制是否“不好”?
【发布时间】:2010-11-23 02:14:47
【问题描述】:

我刚刚在一个项目中发现:

try
{
    myLabel.Text = school.SchoolName;
}
catch
{
    myPanel.Visible = false;
}

我想与开发人员交谈,而不是写这篇文章,说引发空异常(因为理论上school 可能为空,而不是myLabel)实际上会使计算机beep three times and sleep for two seconds。但是,我想知道我是否记错了规则。显然,这不是 try/catch 的预期用途,但这是因为它违背了意图而不好,还是因为性能考虑而不好?我觉得这很糟糕,但我想说的不仅仅是“那真的很糟糕”。

【问题讨论】:

标签: c# try-catch


【解决方案1】:

您不应该仅仅因为它是糟糕的设计而对控制流使用异常。这没有意义。例外是针对例外情况,而不是针对正常流程。在这种情况下,性能可能不会成为问题,因为对于现代硬件上的大多数现代应用程序,您可能会整天抛出异常,而用户不会注意到性能下降。但是,如果这是一个处理大量数据或执行大量某种工作的高性能应用程序,那么是的,性能将是一个问题。

【讨论】:

    【解决方案2】:

    在我看来这很糟糕,因为它可以通过 if 语句更清楚:

    if (school != null) {
        myLabel.Text = school.SchoolName;
    }
    else {
        myPanel.Visible = false;
    }
    

    这肯定会避免不必要地使用异常处理,并使代码的含义非常明显。

    【讨论】:

      【解决方案3】:

      我认为这很糟糕,因为它是针对一个异常进行编码,并且还会继承不必要的开销。仅当要以特定方式处理异常时才应捕获异常。

      应该专门为无法预测的异常情况捕获异常,在这种情况下,只需检查学校是否可以为空,实际上预计学校可能为空(因为标签没有设置)。如果 school 是 null 并且它不应该是 null,那么它应该抛出它自己的 ArgumentNullException。

      【讨论】:

      • 应该是一个空字符串,而不是 NULL。
      • @BillyONeal,school 是一个对象,在这种情况下它有可能为 NULL,这就是异常发生的地方。
      【解决方案4】:

      异常确实会产生运行时开销,但在这里可能可以忽略不计。在调试器中运行会有所不同,但构建的二进制文件应该以几乎相同的速度运行。

      告诉您的开发人员,任何黑猩猩都可以编写机器可以读取的代码。好的代码是为人类而不是机器编写的。如果 null 异常是您唯一担心的事情,那么它可能是用户代码中的错误——没有人应该尝试以这种方式将 null 分配给任何东西。请改用Assert() 语句。

      【讨论】:

      • 我希望我能给这个 +6 分,因为“好的代码是为人类而不是机器编写的。”!我得出的结论是,初级程序员和高级程序员之间的全部区别就是这句话。
      【解决方案5】:

      你说这很糟糕是绝对正确的。这很糟糕,因为它违背了意图,因为它会损害性能。

      我意识到不同的编程风格是有空间的,但就个人而言,我认为即使这样可行,并且我可以看到代码试图做什么,它也会损害可读性和代码清晰度,使其变得更加困难供维护程序员遵循。 if 语句在这里更合适。

      【讨论】:

        【解决方案6】:

        抛出异常确实会对性能产生负面影响,请参阅http://msdn.microsoft.com/en-us/library/ms229009(VS.80).aspx

        【讨论】:

        • 我认为如果你了解它的技术,捕获异常是昂贵的部分。但这并不重要,性能冲击就在那里。
        • 这才是我真正想问的:讨厌编程,或者技术上还可以,因为我们没有抛出异常。 +1 评论。
        【解决方案7】:

        我从不喜欢使用异常来控制流。异常是昂贵的,并且很难确定程序的实际流程是什么,异常被抛出以到达代码中的其他地方。对我来说,这就像使用 GoTo。这并不意味着您应该避免异常,而是异常应该只是程序中通常应该发生的事情的异常。

        我认为代码中更糟糕的部分是它甚至没有做任何异常。没有日志记录,甚至没有解释抛出异常的原因。

        【讨论】:

        • 在 .NET 中,异常并没有那么昂贵,除非您获得堆栈跟踪。在这种特定情况下,很难证明这种异常处理会导致性能问题。
        • 在大范围内,它们并没有那么昂贵,但它们与 if(null == myLabel) 相比。
        【解决方案8】:

        我同意这里的每个人 - 这是一个可怕的想法。

        在 Java 中有一些情况(我认为它们现在大部分已经消失了,但外部库中可能仍然存在一些情况)要求您为某些“非异常”情况捕获异常。

        一般来说,在编写库代码(实际上是任何类)时,应避免对任何可能避免的异常使用异常。如果可能未设置名称字段并且应该在 write() 方法中导致异常,请确保添加 isValid() 方法,以便您实际上不必捕获 write 周围的异常即可知道有问题。

        (Bad Java code addendum):这种“好”的编程风格实际上消除了 Java 中对检查异常的任何需求,而 Java 中的检查异常就是烂。

        【讨论】:

          【解决方案9】:

          查看此post“为什么不使用异常作为常规控制流?”

          【讨论】:

          • 这或多或少是我早上搜索的内容 - 感谢您提供链接,但您可能应该稍微解释一下您的链接是什么或为什么相关,以便其他用户可能会阅读它。其他用户:这是一个广受好评的 SO 问题的链接,标题为“为什么不使用异常作为常规控制流?”
          猜你喜欢
          • 2012-11-25
          • 2012-05-27
          • 2019-10-07
          • 1970-01-01
          • 2016-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多