c# - finally 块下面的代码如何执行?
问题描述
我找不到任何微软官方资源来显示 finally 块下面的代码是如何执行的,关于它的唯一信息是通过 C# 编写的书 CLR,作者说:
如果在 try 块中没有抛出异常,或者如果 catch 块捕获异常并且不抛出或重新抛出异常,则 finally 块下面的代码将执行。
假设我们有以下代码:
class Program {
static void Main(string[] args) {
SomeMethod1();
Console.ReadLine();
}
static void SomeMethod1() {
try {
SomeMethod2();
}
finally {
Console.WriteLine("SomeMethod1 finally");
}
Console.WriteLine("SomeMethod1 last");
}
static void SomeMethod2() {
try {
SomeMethod3();
}
catch (DivideByZeroException e) {
Console.WriteLine("SomeMethod2 caught");
}
finally {
Console.WriteLine("SomeMethod2 finally");
}
Console.WriteLine("SomeMethod2 last");
}
static void SomeMethod3() {
try {
SomeMethod4();
}
finally {
Console.WriteLine("SomeMethod3 finally");
}
Console.WriteLine("SomeMethod3 last");
}
static void SomeMethod4() {
try {
Int32 i = 0;
var c = 3 / i;
}
finally {
Console.WriteLine("SomeMethod4 finally");
}
Console.WriteLine("SomeMethod4 last");
}
}
输出是:
SomeMethod4 finally
SomeMethod3 finally
SomeMethod2 caught
SomeMethod2 finally
SomeMethod2 last
SomeMethod1 finally
SomeMethod1 last
您可以看到“SomeMethod4 last”和“SomeMethod3 last”没有被打印出来。“SomeMethod4 last”不被打印好理解,因为SomeMethod4
抛出异常,并且没有catch块来捕获异常,所以不符合作者规定的要求,还算公平。
但是为什么“SomeMethod3 last”没有被打印出来?没有抛出异常SomeMethod3
,就像SomeMethod1
,那么为什么“SomeMethod1 last”被打印而“SomeMethod3 last”没有?是否有任何 Microsoft 官方资源可以解释其机制?
解决方案
当抛出异常时SomeMethod4
,它会流向调用方法,即SomeMethod3
. 把它想象成这样SomeMethod4
实际上是内联SomeMethod3
的。
static void SomeMethod3()
{
try
{
try
{
Int32 i = 0;
var c = 3 / i;
}
finally
{
Console.WriteLine("SomeMethod4 finally");
}
Console.WriteLine("SomeMethod4 last");
}
finally
{
Console.WriteLine("SomeMethod3 finally");
}
Console.WriteLine("SomeMethod3 last");
}
Last 运行的原因SomeMethod2
是因为它是实际捕获异常的部分。
如果你添加一个 catch 到SomeMethod3
,你会看到它也SomeMethod3 Last
被打印出来了。
异常会中断应用程序的流程,并且在到达 catch 语句之前基本上不会停止返回调用堆栈。从技术上讲,异常被抛出内部SomeMethod1
,但它被捕获SomeMethod2
意味着异常永远不会到达SomeMethod1
。
推荐阅读
- google-cloud-sql - pg_hba.conf 之类的访问控制
- c++ - QT Opengl总是黑屏
- angular - Angular 6 - 在不使用直接链接的路径下发布
- gremlin - 海王星与 Tinkerpop > 如何转义 $ 符号?
- .net - Angular 5:加载资源失败:服务器响应状态为 404
- c# - Automapper AutoMapper.AutoMapperMappingException:错误映射类型
- php - 角度和 PHP
- html - 使用 CSS 调整固定菜单和页面内容
- laravel - 在 Laravel 中存储多个数据
- pyspark - 获取 Spark DataFrame 中两个日期之间的所有日期