Try, Catch... whats the point of Finally?

Z

Z D

Hi,

I was wondering what's the point of "finally" is in a try..catch..finally
block?

Isn't it the same to put the code that would be in the "finally" section
right after the try/catch block? (ie, forget the finally block and just end
the try/catch and put the code after the try/catch block).

Or does the "finally" construct add some additional functionality?

Thanks!
-ZD
 
W

William Ryan eMVP

Finally ensures that whatever is in it will execute no matter what. And no,
there are many intances where the code right after the catch block won't
execute:

try{
DataTable dt;

}
catch(IndexOutOfRangeException ex){

Debug.Assert(false, ex.ToString());
}

MessageBox.Show("We'll Never Get Here");

Since we are only catching an IndexOutOfRange exception, this code would
walk back up the call stack until it found something to catch the Null
ReferenceException - which you may or may not have.

You should use Exceptions to trap Specific things that you know may happen
here or there so you can respond accordingly. Not everything should be
handled and some people will tell you to catch System.Exception everywhere.
If you catch System.Exception then the line after the Try Catch will almost
always execute like you say..but catching System.Exception is very very very
dangerous. It can mask serious problems and give the appearance that
everything is ok when it isn't...or it can lead you on wild debugging
goosechases. After all, in the above code, pretend that It was a function
which returned a boolean. If you caught System.Exception and returned False
when an exception was raised, it may give the appearance that a UserName and
Password didn't match (pretend the function validated a username and
password and returned true if it was found and false if it wasn't) when in
fact they may have but an exception was thrown instead. There are too many
possible examples I could come up with on why you shouldn't catch
System.Exception except in rare instances but that's another discussion.

The short of it is that No, the line of code after the catch won't
necessarily execute and by design, it shouldn't. If you rely on that, you
can end up throwing other exceptions, masking problems and hiding them. So
you should use Finally's liberally, and although C langauages have had them
forever, VB.NET is a much better language because of structured exception
handling (there are many other reasons of course ;-) but this is a big one).

HTH,

Bill
 
M

Mattias Sjögren

Isn't it the same to put the code that would be in the "finally" section
right after the try/catch block?

No. If an exception is thrown that you don't catch, code in the
finally block will run (it always runs) but code after the
try..catch..finally block will not.



Mattias
 
D

Dave

In addition to the other answers, there's a common construct which would
prevent code after the catch from executing...


try
{
// do something exceptional
}
catch(SomeException ex)
{
// do some recovery here
if ( coudntFixIt )
throw new SomeOtherException("I couldn't fix it here.",ex);
}
finally
{
// execute code here no matter what else happens
if ( needsCleaningUp )
{
// do cleanup
}
}

This technique is known as catch-wrap-throw. A variant on this is to catch
and then rethrow the original exception. In both cases the catch block
examines the exception, decide it can't handle it, adds additional context
information, and throws it back up the stack for a handler at a higher level
to deal with.

In all cases the cleanup code is guaranteed to run (there are exceptions to
this but not important here) regardless of how you exit the guarded block of
code.
 
D

D. Yates

Just as a side note for ZD, you don't have to use the finally with a
catch in the same method. The following can stand alone:

try
{
// do something
}
finally
{
// do something else
}

The method call could be protected by a try catch in the calling
method as well or you could let it bubble up to the UI if that's your
desire.....

Dave
 
T

TT \(Tom Tempelaere\)

Mattias Sjögren said:
No. If an exception is thrown that you don't catch, code in the
finally block will run (it always runs) but code after the
try..catch..finally block will not.
Mattias

Suppose a statment in the try-block throws and then code in finally block
also throws? IIUC, The finally block will be executed before stack
unwinding? Tjen you suddenly have two exceptions...
 
D

Dave

You are correct.

A guarded section of code (a try block) must be followed by at least one of
the following types: a finally block, a catch block, or a fault block.
There is no requirement that a catch block be followed by a finally block,
or that a finally block must be preceded by a catch block. In other words

try {} catch{} finally {}
try{} catch{}
try{} finally{}

are all valid.

Fault blocks are defined in the ECMA specs but have not been exposed in the
C# language. These are blocks that execute only if control flow leaves a try
block abnormally, and the code executes during the 2nd pass of the SEH
mechanism.
 
D

Dave

Suppose a statment in the try-block throws and then code in finally block
also throws? IIUC, The finally block will be executed before stack
unwinding? Tjen you suddenly have two exceptions...

There are not two exceptions, the 2nd exception replaces the 1st. Also,
finally blocks are executed after, not before, the stack unwinds.

Ignoring kernel mode transitions, 1st chance exceptions sent to the debugger
, win32 subsystems, transitions in-and-out of unmanaged code, etc, the basic
sequence when an exception is thrown is...

1. 1st pass of stack walking searches the exception frames in the stack for
a catch block to handle the exception. This is based on type filters (for
C#; for VB it may also be user-filtered).
2. If a handler is found it starts the 2nd pass. It remembers where the
catch handler is at and then starts walking the stack again, this time
executing code in finally and fault blocks, up to the frame that contains
the catch block that will handle the exception; it does not yet execute the
finally block associated with that catch block.
3. Control is given to the catch handler. Note that ALL downstream finally
blocks have already run and the stack is unwound to the point of the catch
handler.
4. When the catch handler completes control passes to the finally block (if
any) that follows the catch handler.

If a finally block throws an exception (which is legitimate and happens all
the time) a new exception is thrown and a new sequence of 2 pass stack
walking occurs.

It's also possible for a user-filter to throw its own exception; this is a
nested exception. I believe it replaces the initial exception (in win32 this
would probably be a nested exception). C# does not support user-filtered
exceptions (VB does and I wish C# did too). Also, the CLR does not support
resumable or restartable exceptions (even though the spec states it does; I
frankly think is better off without this).

An important distinction between exceptions thrown in user-filters as
opposed to exceptions thrown in finally or catch blocks is the phase that it
occurs in. Exceptions thrown in user-filters occur during the 1st phase of
the stack walk (before finally blocks have run and before the stack is
unwound) while exceptions thrown in finally and catch blocks occur during
the 2nd phase, which is after all user-filters and downstream (in terms of
the stack) finally blocks have run and the stack has been unwound. If this
occurs a new 2 pass stack walk begins, this time from the site where the new
exception is thrown.

Dave
 
Z

Z D

Wow. William, Mattias, TT, Dave.... I just wanted to thank all you guys for
your excellent responses.

I've found them very helpful and informative.

Best Regards,
-ZD
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top