JUST在捕获中“抛出”是否有益处?

与一位同事进行了激烈的辩论,关于他在try / catch中包装他的大部分function的做法,但抓住它只是一个“扔”,例如

Private sub foo() try 'Do something' catch throw 'And nothing else!' End Try End Sub 

我的想法是甚至不打扰(假设你现在不需要做任何事情) – exception会冒泡到父成员中的下一个exception处理程序。

听起来似乎有道理的唯一论点是,有时exception没有被捕获并且您的代码停止了(在调试模式下),当前行以绿色突出显示…并且这可能与多个线程有关? 最佳实践会声明“每个线程的exception处理程序”,但大多数情况下我们使用单线程。

好处可能是它在调试模式下可能非常有用而不会突然弹出到父成员(是的,Joel!) – 您将转到“throw”语句并能够检查您的本地人。 但是那么你的代码将“乱七八糟地尝试/捕获/抛出”(在这里引用另一个线程)?

如果没有exception发生,那么在任何地方添加try / catch / throws会涉及什么样的开销(即你应该避免在紧密循环中尝试/捕获)?

您在catch中单独抛出而不是抛出新exception的原因是因为这会导致保留原始堆栈跟踪/exception数据。 您可能会这样做的一个原因是因为您现在可以在那里设置一个断点来进行调试。

Microsoft建议您不要捕获exception,因为您唯一要做的就是立即重新抛出它(我现在不记得源代码)。 您的代码应该只捕获您要处理的exception事务或类似操作。

因此,捕获和重新抛出exception通常不是一个好习惯。

用另一个例外捕获和替换它的原因可能是

  • 记录
  • 隐藏来自调用者的敏感信息(Stacktrace,exception详细信息)

对于调试,您可能希望更改“exception时间中断:” – 处理程序(按Ctrl + Alt + e)在所选CLRexception上“抛出”的值。

您可能希望查看entlibexception处理程序块(EHB),使用该块可以建立关于如何处理代码中的exception的模式。

关于你的性能问题,我认为在你的代码中有很多try / catch块并不是一个问题,但是当你的代码引发并捕获许多exception时,你会得到性能命中。

我只会在调试问题时执行此操作 – 并且我会在签入之前再次删除代码。如果抛出exception,有时可以将断点放在特定堆栈级别停止。 除此之外 – 没有。

在实践中,我的想法是,如果你不打算处理错误,不要抓住它。

使用catch和立即重新抛出的一个效果是任何内部“Finally”块将在“Catch”发生之前运行(这将在exception传播之前进行)。 这与两种情况相关:

  1. 如果最终未处理exception,则未处理的exception陷阱可能会退出应用程序而不运行任何“finally”块。 执行捕获并立即重新抛出将确保catch中的所有“finally”块都将执行,即使exception最终未被处理也是如此。
  2. 在运行任何finally块之前,vb.net中的代码以及可能的其他语言可能会对exception起作用。 使用带有catch-and-immediate-rethrow的“try”块将导致该catch块中的“finally”块在任何外部“try”块首次查看exception之前运行。

捕获并立即重新抛出的另一个警告:由于某种原因,捕获和立即重新抛出会丢弃导致exception的函数调用的堆栈跟踪的行号。 我不知道为什么在这种情况下,当前函数在堆栈跟踪中的条目不能单独存在,但事实并非如此。 如果没有使用.pdb文件来获取行号信息,这不是问题,但如果想要使用这些信息,则可能很烦人。

通常,上述效果是不希望的,但是有时前两种效果中的一种或两种可能是有用的,并且第三种效果是可以容忍的。 在这些情况下,立即重新捕获的捕获物可能是合适的,但应记录其原因。

默认情况下总是这样做看起来很糟糕。 但是可能有捕获和抛出的原因,例如你想抛出一个不同的exception。

您不需要catch子句来捕获Visual Studio调试器中的exception。 选择“调试”>“例外”,然后选择要捕获的exception,必要时选择所有exception。

如果捕获exception并将其替换为另一个exception,则通常应将原始exception包装在新exception中。 这通常是通过将旧exception传递给新的构造函数来完成的。 这样你就可以尽可能地挖掘出来,找出发生的事情。 当您不需要隐藏数据时出于安全原因,主要情况就是这样。 在这些情况下,您应该在清除之前尝试记录exception数据。

我所看到的用新包装exception包装exception的理由,而不仅仅是让它们冒出堆栈,exception应该与它们来自的方法处于相同的语义级别。 如果我调用AuthenticateUser,我不希望看到SQLexception。 相反,我应该看到一些exception,其名称告诉我无法完成身份validation任务。 如果我深入研究这个exception的内部exception,我就可以找到SQLexception。 就个人而言,我仍在权衡这样做的利弊。

是的,在捕获中放置一个断点很方便。

一种更干净的方法是在你抛出的对象的构造函数中断点。 您在更接近错误源的位置看到程序状态。

由于没有error handling,这种捕获是没用的。 如果确实有记录或一些清理,但在这种情况下我会摆脱try / catch。

如果您需要检查有关exception的某些内容,并针对某种情况执行某些操作或将其投入其他情况,这也很有用。 例如,如果需要在SQLException中检查错误号。 如果错误编号是您准备处理的错误编号,则可以执行某个操作。 对于其他人,您可以简单地“抛出”它,以便保留堆栈跟踪,如上所述。