finally 块下面的代码如何执行?
Posted
技术标签:
【中文标题】finally 块下面的代码如何执行?【英文标题】:How code below the finally block execute? 【发布时间】:2021-06-21 18:32:44 【问题描述】:我找不到任何微软官方资源显示 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 官方资源可以解释其机制?
【问题讨论】:
【参考方案1】:当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");
SomeMethod2
Last 运行的原因是因为它是实际捕获异常的部分。
如果你给SomeMethod3
添加一个catch,你会看到SomeMethod3 Last
也被打印出来了。
异常会中断应用程序的流程,并且在到达 catch 语句之前基本上不会停止返回调用堆栈。从技术上讲,异常是在SomeMethod1
中引发的,但它在SomeMethod2
中被捕获,这意味着异常永远不会到达SomeMethod1
。
【讨论】:
@Lopop 感谢您的回答,但为什么要打印“SomeMethod1 last”? @amjad 我对帖子的末尾进行了编辑,这可能为时已晚。但原因是因为 SomeMethod2 正在捕获异常。一旦捕获到异常,它就不会继续向上调用堆栈。通过像你一样捕捉它,你实际上是在说“我可以处理这个,不要让其他人知道发生了这个异常”,这就是 SomeMethod1 不受该异常影响的原因。 谢谢。我现在看到了,但不明白为什么没有任何官方的微软资源提到它,他们所有的例子在 finally 块下面都没有代码。 在此处查看此文档...虽然他们没有在 finally 下方添加任何代码,但它们确实包含了一个注释,该注释引用了在 finally 之后运行的更多代码。 docs.microsoft.com/en-us/dotnet/csharp/language-reference/…以上是关于finally 块下面的代码如何执行?的主要内容,如果未能解决你的问题,请参考以下文章
return和finally究竟谁先执行,还有return是怎么返回数据的