-2

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"?

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94
  • 21
    Since you have built your test case, it is unclear to me why you have not run it to find out the answer. – D'Arcy Rittich Oct 25 '11 at 15:29
  • 1
    @RedFilter: because I want to know what is the right behavior in this scenario rather then base my code on a one time test I'm having. finding later on it's a "undefined behavior". – Roee Gavirel Oct 25 '11 at 15:32
  • 3
    If i were asking the question i'd have tried it, then asked a question `This code gives this result, why? Can i rely on this?` – George Duckett Oct 25 '11 at 15:36
  • @Roee: the two are not mutually exclusive. You could run your code and then say, "I observed X, can I rely on this behaviour?" – D'Arcy Rittich Oct 25 '11 at 15:38
  • @GeorgeDuckett: I didn't tried it cause I wouldn't count on a one time try anyway. I just wanted to understand what the standards are saying for this case. – Roee Gavirel Oct 25 '11 at 15:38
  • possible duplicate of [When is finally run if you throw an exception from the catch block?](http://stackoverflow.com/questions/1555567/when-is-finally-run-if-you-throw-an-exception-from-the-catch-block) – D'Arcy Rittich Oct 25 '11 at 15:39
  • 1
    @RoeeGavirel: "I just wanted to understand what the standards are saying" -- OK, **which sentence in the standards document did you find confusing**? I am eager to learn which parts of the standard are confusing so that I can rewrite them to be less confusing. – Eric Lippert Oct 25 '11 at 15:41
  • 1
    Also, I note that you do not say whether the re-thrown exception is caught anywhere. That makes a difference! If it is not caught anywhere then yes, that is undefined behaviour; an unhandled exception is always undefined behaviour. If it is caught then the behaviour is well-defined. – Eric Lippert Oct 25 '11 at 16:06

4 Answers4

5

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

PVitt
  • 11,500
  • 5
  • 51
  • 85
  • So it will execute the "throw" after the finally? – Roee Gavirel Oct 25 '11 at 15:34
  • No, throw is executed before entering the finally block. – PVitt Oct 25 '11 at 15:36
  • 2
    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. – Chris Oct 25 '11 at 15:37
  • @Chris, had that been an answer, +1 IMO, clearer and conciser than your actual answer. – George Duckett Oct 25 '11 at 15:38
  • @Chris this was also my understanding. However, when I tested the code in the question and placed a breakpoint in the `finally` block, it never hit - unless there is some debuggery-trickery going on. – Moo-Juice Oct 25 '11 at 15:40
  • 3
    As Eric Lippert [said](http://stackoverflow.com/questions/1555567/when-is-finally-run-if-you-throw-an-exception-from-the-catch-block), *finally would be a pretty poor choice of keyword if it didn't run last, wouldn't you say?* – D'Arcy Rittich Oct 25 '11 at 15:41
  • @GeorgeDuckett: I was trying to explain the whole try/catch/finally in my answer since the question did start with "I don't understand the order of how these are run". The above comment was dealing solely with the effect of the throw in the catch block and I wasn't sure that was a full enough answer. However, I think I kind of agree with you now given the various comments from the OP so I've updated my answer with that bit. :) – Chris Oct 25 '11 at 15:44
  • @Moo-Juice: I'm going to go with some strange debugger effect until proven otherwise. :) – Chris Oct 25 '11 at 15:46
  • 1
    @Chris: note that the runtime does not *guarantee* execution of the finally. There might be no catch block, in which case it is implementation-defined whether the finally executes or not. Or there might be a catch with an exception filter, and the filter code might failfast the process, in which case the finally does not run. "Finally" does not mean "immediately". – Eric Lippert Oct 25 '11 at 16:04
  • @EricLippert: Ah, I was aware that there were a few cases were it wouldn't run, I hadn't realised that something as potentially common as the lack of a catch could cause this though. Though I am now amused by you being quoted as saying "finally would be a pretty poor choice of keyword if it didn't run last" when you are now saying that in fact it might run at all which isn't really finally. ;-) Thanks for the clarification though. – Chris Oct 26 '11 at 08:50
  • @Chris: *Typically* the runtime prints a message saying that there was an unhandled exception, and then runs the finally blocks. But it need not; for example, the runtime could call a special "there was an unhandled exception in this appdomain" method, and that method could destroy the entire process immediately. That is probably the safer thing to do in fact. There was an unhandled exception; the program is in a maximally messed-up state. Do you really want to be running *finally blocks* at this point, and possibly making things worse? Just bail out, I say. – Eric Lippert Oct 26 '11 at 15:50
3

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.

Chris
  • 27,210
  • 6
  • 71
  • 92
2

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
Paddy
  • 33,309
  • 15
  • 79
  • 114
  • Actually, in putting his code in to practice as he presented it, I put a breakpoint in the `finally` block, called Foo with `0` and it never, ever hit the breakpoint unless I commented out the `throw`. – Moo-Juice Oct 25 '11 at 15:34
  • Did it run the finally block? Because when I ran it although I didn't put in break points it did run the finally block... – Chris Oct 25 '11 at 15:38
0

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

leppie
  • 115,091
  • 17
  • 196
  • 297