Try-Finally是否与Try-Catch一样谨慎使用?

时间:2009-01-04 14:05:52

标签: c# asp.net vb.net exception class

我刚刚读完this article关于异常的优点和缺点,我同意Try-Catch块不应该用于“正常”控制流管理的情绪(不要像使用它们那样使用它们)去)。然而,一位作者提出了关于可维护性(尤其是性能)的好点,这让我对Try-Finally块中的相同内容感到好奇。

我在我的ASP.NET应用程序中使用Try环绕每个连接打开事件,以便我可以确保在最后关闭Connection。在Web应用程序中,泄漏连接显然不是一件好事,我怀疑我是否会改变这种做法,但您的想法是什么?

注意:我确实有连接包装在DAL中,并且可以在调用对象析构函数时关闭连接,但这对我来说似乎很粗略。据我所知,你不能指望在异常情况下调用析构函数。我错了吗?

6 个答案:

答案 0 :(得分:19)

您无需避免try {} ... finally {}模式。但是就你的连接而言,因为它们是IDisposable,所以使用“using”代替,因为它对你来说和更长,更麻烦的try / finally块一样。

答案 1 :(得分:3)

关于在任何地方使用try-catch块的错误的事情是,在消耗异常时你可能隐藏了错误的代码。 Try-finally(没有catch)不会隐藏异常,但确实提供了代码执行保证。在您的情况下,即使从格式良好的SQL命令(例如尝试插入重复行),您也可以期待某些类型的异常,因此我认为使用finally是合理的。这假设您和我一样,认为连接应该是短暂的,并且在使用时应该是打开/关闭的,而不是DAL的生命周期。

编辑:我会选择@Dave Markle的推荐。使用块更优雅,语义相同。唯一一次我倾向于尝试 - 最终过度使用是为了避免多个嵌套使用有利于单个try-finally。

答案 2 :(得分:2)

在有意义的地方使用Try / Finally,在实际出现问题之前不要尝试优化它。

话虽如此,Try / Finally并不像例外那样昂贵。当然,它们不是免费的,但抛出和捕获异常比Try / Finally块更昂贵。

当对象被垃圾收集时,会调用.NET中的“析构函数”,这意味着它可能需要很长时间才能被调用。使用Dispose模式实现确定性资源处理。

答案 3 :(得分:1)

我认为将连接包装在using语句中是更好的做法(假设连接实现了IDisposable)。 dispose方法将检查您的连接状态,并在必要时关闭。

答案 4 :(得分:1)

当对象被垃圾收集时会调用C#析构函数,除了少数边界情况(如果应用程序正在关闭,终结器线程只会这么长,之后它就会被终止)。但这意味着你不知道何时会被调用。在对象被垃圾收集之前可能需要很长时间。所以你是对的,这是一个坏主意。

但是,try / finally通常也没有意义,因为using块会更优雅地实现同样的功能。

答案 5 :(得分:0)

正如其他人所指出的那样,由于在C#中使用了构造,很少需要try-finally。我仍然认为该模型在C ++中是从RAII向后退一步 - 原因是仍然在客户端代码上的负担要记住使用(就像他们必须记住使用try-finally一样)。虽然使用比try-finally更简洁,但如果你习惯使用C ++,它似乎仍然不必要地冗长,特别是当你获得几层嵌套时。

我写了一篇关于如何在一段时间内缓解这个问题的博客文章:

http://www.levelofindirection.com/journal/2009/9/24/raii-and-readability-in-c.html