[英]When is finally run if you throw an exception from the catch block?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
In the above block when is the finally block called?在上面的块中,什么时候调用 finally 块? Before the throwing of e or is finally called and then catch?在抛出 e 之前或最终调用然后捕获?
It would be called after e is re-thrown (ie after the catch block is executed) 在重新抛出e之后(即在执行catch块之后)将调用它
editing this 7 years later - one important note is that if e
is not caught by a try/catch block further up the call stack or handled by a global exception handler, then the finally
block may never execute at all. 7年后编辑这个 - 一个重要的注意事项是,如果e
未被调用堆栈进一步向上捕获或由全局异常处理程序处理,则finally
块可能永远不会执行。
Why not try it: 为什么不尝试一下:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
with code (formatted for vertical space): 带代码(格式化为垂直空间):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
After reading all of the answers here it looks like the final answer is it depends : 在阅读完这里的所有答案后,看起来最终答案取决于 :
If you re-throw an exception within the catch block, and that exception is caught inside of another catch block, everything executes according to the documentation. 如果在catch块中重新抛出异常,并且该异常被捕获到另一个catch块内,则所有内容都根据文档执行。
However, if the re-trown exception is unhandled, the finally never executes. 但是,如果重新处理的异常未处理,则finally永远不会执行。
I tested this code sample in VS2010 w/ C# 4.0 我在VS2010 w / C#4.0中测试了这段代码示例
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
Here is the output: 这是输出:
Example 1: re-throw inside of another try block: 示例1:重新抛出另一个try块:
--outer try - 外出尝试
----inner try ----内心尝试
----inner catch ----内心抓住
----inner finally ----内心终于
--outer catch - 外部捕获
--outer finally - 最后
Huzzah! 好哇!Example 2: re-throw outside of another try block: 示例2:在另一个try块之外重新抛出:
--try - 尝试
--catch - 抓住Unhandled Exception: System.Exception: Exception of type 'System.Exception' was thrown. 未处理的异常:System.Exception:抛出了类型'System.Exception'的异常。
at ConsoleApplication1.Program.Main() in C:\\local source\\ConsoleApplication1\\Program.cs:line 53 在C:\\ local source \\ ConsoleApplication1 \\ Program.cs中的ConsoleApplication1.Program.Main()中:第53行
Your example would behave identically to this code: 您的示例与此代码的行为相同:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
As a side note, if you really mean throw e;
作为旁注,如果你的意思是throw e;
(that is, throw the same exception you just caught), it is much better to just do throw;
(也就是你扔刚好赶上了同样的异常),它是要好得多只是不throw;
, since that will preserve the original stack trace instead of creating a new one. ,因为这将保留原始堆栈跟踪而不是创建新的跟踪。
If there is an unhandled exception inside a catch handler block, the finally block gets called exactly zero times 如果catch处理程序块中存在未处理的异常,则finally块将被调用为零次
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
Output: 输出:
C:\\users\\administrator\\documents\\TestExceptionNesting\\bin\\Release>TestExceptionNesting.exe C:\\用户\\管理员\\文件\\ TestExceptionNesting \\ BIN \\发布> TestExceptionNesting.exe
in the try 在尝试
in the catch 在捕获
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. 未处理的异常:System.DivideByZeroException:尝试除以零。 at TestExceptionNesting.Program.Main(String[] args) in C:\\users\\administrator\\documents\\TestExceptionNesting\\TestExceptionNesting.cs:line 22 在TestExceptionNesting.Program.Main(String [] args)中的C:\\ users \\ administrator \\ documents \\ TestExceptionNesting \\ TestExceptionNesting.cs:第22行
C:\\users\\administrator\\documents\\TestExceptionNesting\\bin\\release> C:\\用户\\管理员\\文件\\ TestExceptionNesting \\ BIN \\发布>
I got asked this question today at an interview and the interviewer kept going back "are you sure the finally doesn't get called?" 今天我在接受采访时被问到这个问题,面试官一直回过头来说“你确定最终没有被召唤吗?” I was uncertain if it was meant a trick question or the interviewer had something else in mind and wrote the wrong code for me to debug so I came home and tried it (build and run, no debugger interaction), just to put my mind at rest. 我不确定这是否意味着一个技巧问题,或者面试官是否有其他想法,并为我编写了错误的代码进行调试,所以我回家试了一下(构建并运行,没有调试器交互),只是为了让我的想法休息。
一个简单的方法是调试代码并在最终调用时注意。
Testing with a C# Console Application, the finally code has been executed after the exception is thrown: The "Application Error Dialog" existed and after you chose "Close the program" option, the finally block was executed in that console window. 使用C#控制台应用程序进行测试后,最终代码在抛出异常后执行:“应用程序错误对话框”已存在,在您选择“关闭程序”选项后,最终块在该控制台窗口中执行。 But setting the breaking point inside the finally code block, I can never hit it. 但是在最终代码块中设置断点,我永远不会打它。 The debugger keeps stopping at the throw statement. 调试器一直停在throw语句处。 Here is my test code: 这是我的测试代码:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
Debugging in VS2010 - .NET Framework 4.0 在VS2010中进行调试 - .NET Framework 4.0
You can do it, I have done this to ensure cleanup.你可以做到,我这样做是为了确保清理。
using System;
class Program
{
static void Main()
{
FinallyThrow();
Console.ReadLine();
}
static void FinallyThrow()
{
// Get finally block to execute EVEN IF there is an unhandled exception
Exception thrownEx = null;
try
{
Console.WriteLine("try..");
throw new InvalidOperationException();
}
catch (Exception ex)
{
Console.WriteLine("catch..");
thrownEx = ex;
}
finally
{
Console.WriteLine("finally..");
if (thrownEx != null) throw thrownEx;
}
}
}
OUTPUT (after breaking to the unhandled exception) OUTPUT(中断到未处理的异常后)
try..
catch..
finally..
. . Finally always run even if unhandled exception最终总是运行,即使未处理的异常
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.