try-catch-finally 执行顺序

发布于 2024-12-11 13:46:18 字数 835 浏览 0 评论 0原文

我在理解 try-catch-finally 的执行顺序时遇到问题。我见过的所有示例(例如:http://stackoverflow.com/questions/4191027/order-of-execution-of-try-catch-and-finally-block)都有一个非常简单的“catch”部分,打印到控制台。但是如果我在 catch 中使用“throw”语句会发生什么?

我能想到的最简单的代码可以解决问题:

public class TestClass
{
    void Foo(int num)
    {
        int answer = 100;
        try
        {
            answer = 100 / num;
        }
        catch (Exception e)
        {
            //Probably num is 0
            answer = 200;
            throw;
        }
        finally
        {
            Console.WriteLine("The answer is: " + answer);
        }
    }
}

如果 num == 2,那么输出将是:

答案是:50

但是 num == 0 会打印什么呢?

答案是:100
答案是:200
根本没有打印...

或者这只是一个“未定义的行为”?

I'm having a problem understanding the order of execution for the try-catch-finally. All the example I've seen (like in:http://stackoverflow.com/questions/4191027/order-of-execution-of-try-catch-and-finally-block) have a very simple "catch" part which print to console. but what happen if I use a "throw" statement in the catch?

The simplest code I could think of which capture the problem:

public class TestClass
{
    void Foo(int num)
    {
        int answer = 100;
        try
        {
            answer = 100 / num;
        }
        catch (Exception e)
        {
            //Probably num is 0
            answer = 200;
            throw;
        }
        finally
        {
            Console.WriteLine("The answer is: " + answer);
        }
    }
}

If num == 2, then the output will be:

The answer is: 50

But what would be printed for num == 0?

The answer is: 100
The answer is: 200
No printing at all...

or is it just a "undefined behavior"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

埋情葬爱 2024-12-18 13:46:19

根据对另一个答案的评论的普遍要求:

它将立即执行抛出。所以 catch 块中的任何代码
throw之后不会被执行。但是,它会执行
最后在将抛出的异常传递给适当的之前
父级。

原始答案

您的代码将执行 try 块。如果成功,它将运行finally 块。然后它就会结束。

如果 try 块在某处抛出异常,那么它将立即停止执行并开始执行 catch 块(假设捕获了异常类型)。一旦catch块执行完毕,它将执行finally块。然后在这种情况下,它将把抛出的错误传播到堆栈上。

编辑添加:是的,它将打印 200 作为答案,因为在 catch 块重置答案后,final 是要运行的最后部分。

By popular demand from a comment to another answer:

it will execute the throw immediately. So any code in the catch block
after the throw will not be executed. However, it will execute the
finally before passing the thrown exception up to the appropriate
parent.

Original answer

Your code will execute the try block. If this succeeds fine it will run the finally block. It will then end.

If the try block throws an exception somewhere then it will immediately stop executing at that point and start executing the catch block (assuming that exception type is caught). Once the catch block has finished executing it will execute the finally block. Then in this case it will propogate the thrown error up the stack.

Edited to add: yes, it will print 200 as the answer becuase the final is the final part to run, after your catch block has reset the answer.

情栀口红 2024-12-18 13:46:19

最简单的测试方法就是尝试一下。它应该打印 - 答案是 200,然后出错。

finally 总是会被调用(除了一些无法捕获的异常,例如堆栈溢出)。您应该注意不要在finally块中抛出异常...

这里您的流程将是:

exception caused
caught
answer variable set
exception thrown
finally block executed
exception propogated up the stack

The easiest way to test is to try it. It should print - the answer is 200, and then error out.

Finally will always be called (except for some exceptions that cannot be caught, e.g. stack overflow). You should take care to try and not throw an exception from within your finally block...

Here your flow will be:

exception caused
caught
answer variable set
exception thrown
finally block executed
exception propogated up the stack
秋意浓 2024-12-18 13:46:19

这很难解释,但通常当退出范围(在您的情况下是堆栈框架)时,finally 子句将执行。

It is difficult to explain, but generally when the scope (which is the stackframe in your case) is exited the finally clause will execute.

赠我空喜 2024-12-18 13:46:18

如果try块内发生异常,则执行catch块内的代码。如果有多个 catch 块,则会执行与捕获的异常最匹配的那个。

class A : System.Exception {}
class B : A {}

void Test()
{
    try
    {
        throw new B();
    }
    catch (A a)
    {
        //as B is derived from A, this catch block will be invoked.
    }
    catch (Exception e)
    {
    }
}

最后块被执行了。是否发生异常并不重要。

[编辑]
为了进一步澄清顺序(感谢评论)

void Test()
{
    Debug.WriteLine("1");
    try
    {
        Debug.WriteLine("2");
        throw new Exception();
        Debug.WriteLine("3");
    }
    catch
    {
        Debug.WriteLine("4");
        throw;
        Debug.WriteLine("5");
    }
    finally
    {
        Debug.WriteLine("6");
    }
    Debug.WriteLine("7");
}

将打印的内容是:

1
2
4
6

3 没有被打印,因为在它之前抛出了一个异常。由于 catch 块中的 throw,因此 5. 7 也不会打印。

[/编辑]

所以回答你的问题:答案是:200

If an exception occurs inside the try block, the code inside the catch block is executed. If you have several catch blocks, the one that matches the caught exception best is excuted.

class A : System.Exception {}
class B : A {}

void Test()
{
    try
    {
        throw new B();
    }
    catch (A a)
    {
        //as B is derived from A, this catch block will be invoked.
    }
    catch (Exception e)
    {
    }
}

The finally block is executed after all. It doesn't matter whether or not an exception occured.

[EDIT]
To clarify the order a bit more (thanks to the comments)

void Test()
{
    Debug.WriteLine("1");
    try
    {
        Debug.WriteLine("2");
        throw new Exception();
        Debug.WriteLine("3");
    }
    catch
    {
        Debug.WriteLine("4");
        throw;
        Debug.WriteLine("5");
    }
    finally
    {
        Debug.WriteLine("6");
    }
    Debug.WriteLine("7");
}

What will be printed is:

1
2
4
6

3 is not printed because an exception si throw before it. The same for 5. 7 is not printed because of the throw in the catch block.

[/EDIT]

So answering your question: The answer is: 200

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文