免责声明:众所周知try {
...
} catch {
throw;
}
is bad practice。这个问题不。
在挖掘Microsoft参考资源时,我注意到a lot of methods中的以下模式:
catch { throw; }
没有记录,没有调试代码 - 只是简单的try-finally
。
显然,微软的人应该相当熟练使用C#,这样做的重点是什么,而不是仅仅省略catch块(和try语句)? 这样的编码有技术原因,还是纯粹的风格选择?
注意:我不知道它是否相关,但是我能找到的所有这些实例都包含嵌套在try
子句内的try-catch
块{1}}阻止。
答案 0 :(得分:12)
它会影响异常过滤器的运行时间。
鉴于
void f() {
using (var x = AcquireResource()) {
x.DoSomething();
x.DoSomethingElse();
}
}
与
void f() {
try {
using (var x = AcquireResource()) {
x.DoSomething();
x.DoSomethingElse();
}
} catch {
throw;
}
}
与
void g() {
try {
f();
} catch (Exception ex) when (h()) {
// ...
}
}
f
的第一个版本允许在h()
处置之前调用过滤器x
。 f
的第二个版本可确保在运行外部代码之前处置x
。
在您链接到的代码中,SqlConnectionHolder
被大量使用,catch { throw; }
块围绕SqlConnectionHolder
使用。
答案 1 :(得分:7)
正如C# Specification所述:
发生异常时,系统会搜索最近的
catch
子句,该子句可以处理异常,由异常的运行时类型决定。首先,在当前方法中搜索词法封闭的try
语句,并按顺序考虑catch
语句的关联try
子句。如果失败,则搜索调用当前方法的方法,以查找包含对当前方法的调用点的词法封闭try
语句。此搜索将继续,直到找到可以处理当前异常的catch
子句,方法是命名与抛出的异常的运行时类型相同的类或基类的异常类。没有命名异常类的catch
子句可以处理任何异常。一旦找到匹配的
catch
子句,系统就会准备将控制转移到catch
子句的第一个语句。在开始执行catch
子句之前,系统首先按顺序执行与finally
语句相关联的任何try
子句,这些子句比捕获异常的语句更嵌套。
在异常运行时首先查找可以处理它的catch
子句,其中涉及执行任何关联的异常过滤器。不加区别的catch
阻止中断,搜索并立即执行所有嵌套finally
块。
当您想要阻止调用者在finally
阻止之前执行任意代码(以异常过滤器的形式)时,这可能很有用。例如,当finally
块影响当前线程的安全上下文时。
此外,如果任何catch
子句都不会捕获异常,那么它将导致线程终止。在这种情况下,C#规范没有提供任何保证,任何finally
块都将被执行。
如果搜索匹配的catch子句到达最初启动该线程的代码,则终止执行该线程。这种终止的影响是实现定义的。
答案 2 :(得分:-2)
您链接的代码实际上是一个很好的例子。
在我看来,在处理他们无法控制的事情时,应该只使用 try catch 块,比如文件系统,外部事物。
在您链接的代码中, try catch 是围绕数据库的东西。
这意味着通过使用这种编码方式,他们确保没有泄漏,没有连接保持打开状态。
如果出现任何问题,例如错误的连接字符串,缺少表,等等,代码将继续执行,它将正常关闭连接,如 finally 块中所示,它将最后抛出意味着它将允许该代码的客户端获得正确的异常,同时获取整个堆栈并让他们决定在发生这种情况时该怎么做。
说实话,我非常喜欢他们在那里所做的事。