views:

1402

answers:

13

I see that the Finally in try .. Catch will execute allways after any parts of the execution of the try catch block.

Is it any different to just skip the Finally section and just run it after, outside the try catch block??

Example 1, Try ... Catch ... Finally ... End Try

    Try
        'Do something
    Catch ex As Exception
        'Handle exception
    Finally
        'Do cleanup
    End Try

Example 2, Try ... Catch ... End Try ... Do the finally stuff outside

    Try
        'Do something
    Catch ex As Exception
        'Handle exception
    End Try
    'Do cleanup
+2  A: 

The difference is when the code in the try block throws an exception that isn't caught by the catch block.

Normally a catch block would catch a specific type of exception, and let anything else through. In that case, the finally block will still run.

The finally block will also run if the code in the try block returns.

RichieHindle
+1: good point with uncaught exception types
Fredrik Mörk
it doesn't matter whether the exception is caught or not. The finally block always run (baring exceptional conditions such as "brute force" application exits)
Rune FS
@Rune FS: Yes, but if the exception is caught, there's no difference between awe's two examples (barring further exceptions being raised, `return` statements, etc.). If it isn't caught, there *is* a difference. That's what awe was asking about.
RichieHindle
+5  A: 

Finally contains code that needs to be evaluated at all conditions [whether or not an exception occurred].

There is no way to exit a try block without executing its finally block. If the finally block exists, it always executes. (This statement is true for all intents and purposes. There is a way to exit a try block without executing the finally block. If the code executes a System.exit(0); from within a try block, the application terminates without the finally executing. On the other hand, if you unplug the machine during a try block, the finally will not execute either.)

The main use is for disposing objects. It will be useful when you want to close user defined resources like file , opened resources(db stmts).

Edit

Also finally won't be executed after a stackoverflow exception.

rahul
Will the finally block be executed if there is a StackOverflowException?
Colin Mackay
No, it won't be executed.
rahul
This assumes that the process doesn't terminate abruptly.
rahul
Thanks. Edited my post.
rahul
+1  A: 

you use finally for cleanup code, eg db connections or files that are open that needs to be close. Virtually any cleanup code that needs to execute regardsless of an exception or not

also, your exception handling might require to re throw the exception, or other exception, in which case the code after the block will not be executed

astander
+29  A: 

Yes, it is different. Finally will always run (barring program crash). If the function exits inside of the try catch block, or another error is thrown in either the try or the catch, the finally will still execute. You won't get that functionality not using the finally statement.

Kevin
Unfortunately `finally` blocks run *by default* if the program crashes in various ways. But you can override this if you want: handle `AppDomain.UnhandledException` to call `Environment.FailFast`.
Daniel Earwicker
Although if you're a Java programmer, you're out of luck: unhandled exceptions execute `finally` blocks and there's nothing you can really do about it.
Daniel Earwicker
Well, you can do something about it, you can design/write your code so it doesn't use Exceptions for flow control and don't use the finally block for similar things. Finally should be used for cleaning up, which should always occur.
PintSizedCat
Not true, there are times when finally may not be called. Like aborting the program from the OS, or the computer crashing.
Kevin
The two ways it will not execute are when the thread executing the try/catch stops executing or the JVM is terminated. So the thread may stop and the rest of the program continues and you would never know (barring good logs / coding) whether it ran or not.
amischiefr
+2  A: 

This is a good idea when dealing with database connections or anytime objects need to be disposed of. Just in case something goes wrong while running queries, you can still close the connection safely. It also helps to clean up code that the block outside the try/catch/finally block is not able to access.

scheibk
+1  A: 

Doing clean up in a finally block is to ensure that it is run. If the catch block doesn't deal with the exception (ie. it just logs it), or even causes another exception, the code in the finally block will still run.

adrianbanks
A: 

Catch will not run after any parts of the execution of the try catch block. Catch will only run if an exception is thrown and the catch block can handle that type of exception.

The finally block is the one that will run when the try block is complete. By complete, I mean it finishes normally, or exits in some way (breaks out of a loop, returns from the method, throws an exception, etc.)

If you put the code outside the finally block and an exception is thrown (for example) then the code may not be executed if the exception is not caught, or it is rethrown in the catch block, or an new exception is thrown in the catch block. If you put it inside the finally block then it will be executed.

Basically, the clean up should be put in the finally block.

Colin Mackay
This is not what I asked. I was asking if it is a difference between running code in the ´finally´ block vs. running code after (outside) the entire try-catch block (not inside catch).
awe
+1  A: 

On top of what everyone else said, semantically I think that they are different.

Code in the finally block clearly states that you're doing finalization type tasks for the content contained within the try-catch. I think this makes it clearer to read.

Giovanni Galbo
I totally agree with you on this. I was just curious if it was any technical difference, and based on what others have said, it is...
awe
+2  A: 

The Finally block will execute regardless of if the function exits because of an exception. (there are some exceptions to this rule, see this stackoverflow question for more info).

For example:

Try
    'Do something
Catch ex As Exception
    if 'Some Condition
       throw ex
    else
       'Handle exception
Finally
    'Do cleanup
End Try

In this case the Finally block will still be executed even though you may throw an exception out of the function.

This is a good practice to get into because it ensures that your cleanup code always executes. Of course using the Resoource Acquisition Is Initialization idiom is a much cleaner way of ensuring that resources get cleaned up, but I'm not versed enough in VB.net to know if this is possible to do.

Nick Haddad
"always"? There are a number of reasons a finally block won't run.
Colin Mackay
@Nick: note that the finally block is not *guarateed* to always run; there are some exceptions (!) to this rule; StackOverflowException being one of them.
Fredrik Mörk
Unplugging the computer while in the middle of the try block will also cause the finally not to execute :)
Giovanni Galbo
Oy, forgive my ignorance of the CLR. I've edited my post.
Nick Haddad
+4  A: 

Code with four radio buttons:

  • Return in TRY
  • Return in CATCH
  • Throw in CATCH
  • Finish CATCH

    private void checkFinally()
    {
        try
        {
            doFinally();
        }
        catch
        {
            Console.WriteLine(" Breaking news: a crash occured. ");
        }
    }
    
    
    private void doFinally()
    {
        Console.WriteLine(" ");
        Console.Write("Here goes: " 
            + (radioReturnInTry.Checked ? "2. Return in try: " 
                    : (radioReturnInCatch.Checked? "3. Retrun in catch: "
                        : (radioThrowInCatch.Checked? "4. Throw in catch: "
                            : "1. Continue in catch: "))) );
        try
        {
            if (radioReturnInTry.Checked)
            {
                Console.Write(" Returning in try. ");
                return;
            }
            Console.Write(" Throwing up in try.  ");
            throw new Exception("check your checkbox.");
        }
        catch (Exception ex)
        {
            Console.Write(" ...caughtcha! ");
            if (radioReturnInCatch.Checked)
            {
                Console.Write("Returning in catch. ");
                return;
            }
            if (radioThrowInCatch.Checked)
            {
                Console.Write(" Throwing up in catch. ");
                throw new Exception("after caught");
            }
        }
        finally { Console.Write(" Finally!!"); }
        Console.WriteLine(" Done!!!"); // before adding checkboxThrowInCatch, 
        // this would never happen (and was marked grey by ReSharper)
    
    
    }
    


Output:

  • Here goes: 1. Continue in catch: Throwing up in try. ...caughtcha! Finally!! Done!!!
  • Here goes: 2. Return in try: Returning in try. Finally!!
  • Here goes: 3. Retrun in catch: Throwing up in try. ...caughtcha! Returning in catch. Finally!!
  • Here goes: 4. Throw in catch: Throwing up in try. ...caughtcha! Throwing up in catch. Finally!! Breaking news: a crash occured.


To summarize: Finally takes care of two things:

  1. Of code that returned in the try or in the catch.
  2. Or If you had an exception in the try, AND THROW an exception in the catch,
  3. or, if you had an exception in the try, AND DID NOT CATCH that exception,

Finally to summarize "FINALLY": Finally does nothing special if you tried,and

  1. DID NOT RETURN,
  2. and caught any exceptions during the trial, and then
  3. DID NOT RETURN in the catch either, and
  4. DID NOT THROW or have code that throws up.

And last but not least (finally): If you have an exception in your code that YOU DID NOT CATCH, your code will fly, WITHOUT REACHING THE FINALLY.

Hope this is clear. (Now it is to me...)

Moshe

pashute
A: 

After reading the reply to my comment above I came to think of a few things.

The question can basically not be answered completely with out knowing the code in question.

The reason being that not all code can be put in a finally block. E.g. yield statements are not allow in finally (and catch) blocks. The try block might have several execution braches where some returns and some don't. The finally being executed in all those case whereas in the example with no finally that would not be the case for the clean up code. Further more you can't jump (goto) into a finally block though very uncommon you can jump to the code after the catch block. You can't return from a finally block either.

There's quite a few although most very uncommon cases where the answer depends on the actual code.

Rune FS
+1  A: 

As far as I can remember I have never used a try/catch/finally block in my .NET code.

In general, catching exceptions in the middle tier is rarely needed. Exceptions are usually propagated to a top-level handler in the presentation tier (and possibly caught and rethrown at a tier boundary so they can be logged).

So in the middle tier you will more often see try/finally (or the "using" statement) so that resources are cleaned up. And in try/catch in the top-level handler in the presentation tier.

In the rare cases that I need to both catch an exception and do some cleanup, I would prefer to refactor so that the following:

try
{
    ... do something
}
catch
{
   ... handle exception
}
finally
{
   ... cleanup
}

becomes:

try
{
    DoSomethingAndCleanup();
}
catch
{
   ... handle exception
}

...
private void DoSomethingAndCleanup()
{
    try
    {
        ... do something
    }
    finally
    {
        ... cleanup
    }
}

IMHO this is much cleaner.

Joe
Cathcing exceptions in the middle tier would make sense if the original exeption is caused something that does make sence in the internal code but not out in the presentation tier. It would then make sense to throw an exception that gives more detail about the context for what actually went wrong.
awe
A: 

What I often use is (I encapsulated that into an aspect, but this is what I derived the aspect of):

public static DoLengthyProcessing(this Control control, Action<Control> action)
{
    Cursor oldCursor = control.Cursor
    try
    {
        control.Cursor = Cursors.WaitCursor;
        action(control);
    }
    catch (Exception ex)
    {
        ErrorHandler.Current.Handler(ex);
    }
    finally
    {
        control.Cursor = oldCursor;
    }
}

Or, use AOP (as I do).

stormianrootsolver