C#的Try/Catch/Finally

4

在编写代码时,我一直被告知要尽可能避免使用try/catch/finally块。这样做的原因对我来说总是很有道理(如果应用程序按照预期工作,就不需要防止错误),但与此同时,有许多可能导致错误的原因并非由于糟糕的编码;服务器故障、图形似乎永远不会在没有明显原因的情况下失败等等。我还被告知这些块会降低性能,但我个人使用它们时并没有注意到什么问题,但我想这可能是有道理的。总之,我的问题是:Try/Catch/Finally是一个整体上的坏主意,还是像其他某些东西一样,在某些情况下好,在过度使用的情况下对于糟糕的代码来保持应用程序运行良好,对于测试来说是好的,对于生产来说是坏的?我只是想听听大家的意见。


5
像所有的语言特性一样,try/catch能被用于好的和坏的情况。通常应避免使用catch来控制程序流程。我认为"finally"不属于你所说的类别,它是确保某些情况下的资源清理工作绝对必要的。我认为做出一项笼统的"不要使用它"的决定是不明智的。你需要评估每种情况,找到最佳解决方法。有时候,try/catch是一个答案。 - vcsjones
1
请阅读此文章:http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx - asawyer
2
经验法则非常简单...如果可能发生异常,就将其包装在异常处理程序中。不仅要捕获异常,而且要以某种方式有意义地处理它。这一切都是推测,没有具体的例子。你能否更新问题,提供一个你使用try/catch/finally的具体实例,而你被告知它是不正确的? - David
3
如果文件无法访问,File.ReadAllText 将抛出异常 - 如何在不使用 try/catch 的情况下处理这种情况? - joe
4
我相信 catch 块几乎没有性能影响(如果有的话)。抛出异常才会导致性能下降,因为需要进行堆栈的回溯和展开。 - dcastro
显示剩余9条评论
5个回答

5

有些情况下你不能避免使用Try/Catch,

考虑一种情况,你想让用户输入一些数据并将其输入到数据库表中。用户的输入包括主键,如果某个用户输入了重复的主键,你将会得到一个异常。现在你想做什么?让系统崩溃还是处理异常并向用户显示友好的消息以输入不同/唯一的内容。

举个例子,假设你想检查某个URL是否有效和可用,你可能需要一些方法,例如:(从这里获取)

private bool IfURLExists(string url)
{
    try
    {
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        request.Method = "HEAD";
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
        return (response.StatusCode == HttpStatusCode.OK);
    }
    catch //may catch specific WebException First
    {
        return false;
    }
}

上述方法没有try/catch的话无法工作。 try/finally的另一个重要用途是与using语句一起使用,using用于实现IDisposable接口的对象,并转换为try/finally块,因此如果发生异常,它将确保处理未经管理的资源的处置。
通常只捕获那些你想对其进行有用处理的异常,否则就让异常冒泡

1
在这种情况下,论点是进行错误检查并确保在插入新记录之前键不存在。不仅仅等待SQL异常返回。 - Volearix
不是一个很好的例子,但是重要的是思想。 - asawyer
2
@Volearix 和 deterministicFail,这只是一个例子... - Habib
3
提前检查是愚蠢的,因为在检查和实际操作之间可能会发生变化。将所有内容序列化以便提前正确检查并确保不会改变是非常愚蠢的。 - Ralf
2
@deterministicFail,已删除示例并添加了一些新内容。 - Habib

2

如果以合理的方式使用try/catch/finally块,则没有任何问题。

作为开发人员,您甚至无法想象客户与您的思维有多不同,或者您的系统将如何与不同的系统交互或对您未考虑的输入做出反应。

唯一的规则是:不要滥用。


2
实际上,我会删除关于用户输入的部分。你不应该通过抛出/捕获异常来验证用户输入 - 无效的输入并不真正是“异常”的情况。 - dcastro
我认为这取决于输入。在某些情况下,您可能需要解析格式不良的文档;用户输入不仅限于用户必须填写的表单字段。 - DocKuro

2
这个人完全没有说明为什么要完全摆脱try/catch/finally。我甚至不明白为什么finally块会出现在这里?没有finally,你如何可靠地清理资源呢?
C#语言提供了使用语句,它实际上是在try/finally结构上实现的一种语法糖,那么这是错误的吗?或者滥用了吗?你能否在没有try/finally的情况下实现一个using块?
foreach使用try/finally,以及许多需要它的地方。
典型例子:考虑“套接字编程”,当处理套接字时,你如何避免捕获SocketException和IOException?这是实际可行的吗?肯定不是。它们应该在需要时使用。
结论:try/catch/finally应该按照其预期的方式使用。你不应该吃掉异常,但这并不意味着你必须让异常终止你的进程。你必须处理它。

1

一个基本的规则是在你可以处理异常时捕获它们。如果你无法处理它们,就让它们通过。程序进程中未被捕获的任何异常最终处理可能是记录并向用户显示错误消息。


1
你应该只捕获自己能够处理的异常,其他异常应该向上抛出。绝对不要捕获像 NullReferenceExceptionArgumentOutOfRangeException 这样的异常。这些都是 bug,捕获会隐藏代码中的这些问题。
关于此主题的文章:令人烦恼的异常

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接