Try... Catch... Finally blocks

G

Grim Reaper

Just a quick and probably daft question...

Isn't the code;

Try
DoSomething()
Catch e As Exception
HandleError(e)
Finally
DoThisAtTheEnd()
End Try

functionally identical to...

Try
DoSomething()
Catch e As Exception
HandleError(e)
End Try
DoThisAtTheEnd()

What I'm getting at, is that I don't really see the point of the Finally statement! Surely after the Catching and handling has been dealt with, the code will move on to whatever is after the End Try anyway?!?
Your comments appreciated... :D
____________________________________________
The Grim Reaper
 
C

Cowboy \(Gregory A. Beamer\)

Yes, unless you end up with an error inside of your HandleError:

Try
DoSomething()
Catch e As Exception
HandleError(e)
Finally
'This will still run
DoThisAtTheEnd()
End Try


Try
DoSomething()
Catch e As Exception
HandleError(e)
End Try

'This will not run now
DoThisAtTheEnd()

Private Sub HandleError(ByRef ex As Exception)
Dim i As Integer = 1
Dim j as Integer = 0

'Intentional divide by zero error
'simulates bad handling, like logging routine cannot
'access database server (SQL Error?)
Dim k as Integer = i/j

End Sub

--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA

***********************************************
Think Outside the Box!
***********************************************
"Grim Reaper" <gdewdneyatsilvertechcouk> wrote in message
Just a quick and probably daft question...

Isn't the code;

Try
DoSomething()
Catch e As Exception
HandleError(e)
Finally
DoThisAtTheEnd()
End Try

functionally identical to...

Try
DoSomething()
Catch e As Exception
HandleError(e)
End Try
DoThisAtTheEnd()

What I'm getting at, is that I don't really see the point of the Finally
statement! Surely after the Catching and handling has been dealt with, the
code will move on to whatever is after the End Try anyway?!?
Your comments appreciated... :D
____________________________________________
The Grim Reaper
 
G

Grim Reaper

Ahhhh.... I see.
I was obviously still inside my box.. (it is Monday after all)

Cheers!
_____________________________________
The Grim Reaper
 
G

Guest

What I'm getting at, is that I don't really see the point of the Finally
statement!

1. In a Finally clause, any Dim'ed variables will go out of scope when the
Try block finishes.

2. If you exit a try block with a Goto, the Finally block will be executed
before the Goto (Documentation says this, I never tried it out).
 
H

Herfried K. Wagner [MVP]

AMercer said:
2. If you exit a try block with a Goto, the Finally block will be
executed
before the Goto (Documentation says this, I never tried it out).

That's true. It's even executed if you exit procedure using 'Return' or
'Exit...'.
 
T

The Grim Reaper

Now that IS interesting...
I don't think I would put a Return or Exit statement inside a Try block in
the first place,
but that certainly could cause problems.

So finally is basically saying "do this before you leave the block -
whatever".
______________________________________
The Pished Reaper
 
W

wooster11

Another good thing to put in your finally is your disposal or closing
of objects. Great for DB Connections.

Try
dim SqlCn as SqlConnection..

'Excute your statement
Catch Ex as Exception
throw ex
Finally
if SqlCn.ConnectionState = Open Then SqlCn.Close
SqlCn.dispose
End Try

This will always guarantee that you have a closed connection to your
database. This saves you from having to write that code twice, say in
the Try and in the Catch.
I use the Finally all the time.

Derek Woo
 
T

Tom Shelton

wooster11 said:
Another good thing to put in your finally is your disposal or closing
of objects. Great for DB Connections.

Try
dim SqlCn as SqlConnection..

'Excute your statement
Catch Ex as Exception
throw ex
Finally
if SqlCn.ConnectionState = Open Then SqlCn.Close
SqlCn.dispose
End Try

This will always guarantee that you have a closed connection to your
database. This saves you from having to write that code twice, say in
the Try and in the Catch.
I use the Finally all the time.

Derek Woo

Just thought I'd point out - that the Catch in your example is really not
necessary, since your just re-throwing the exception. I would probably
just do this:

Dim connection As SqlConnection = Nothing

Try
' create the connection
' execute your stuff
Finally
' dispose of your objects
End Try

The functional result is that the exception is thrown, just as yours does
and your resources are still released. I do this all the time in my C#
code :)
 
G

Greg Burns

I thought I'd read somewhere that

Throw ex

behaved differently than just

Throw

all by itself?

Greg
 
G

Greg Burns

http://www.codeproject.com/dotnet/exceptionbestpractices.asp
Don't clear the stack trace when re-throwing an exception
The stack trace is one of the most useful information that an exception
carries. Often, we need to put some exception handling on catch blocks
(e.g., to rollback a transaction) and re-throw the exception. See the right
(and the wrong) way of doing it: The wrong way:
try
{
// Some code that throws an exception
}
catch (Exception ex)
{
// some code that handles the exception
throw ex;
}
Why is this wrong? Because, when you examine the stack trace, the point of
the exception will be the line of the "throw ex;", hiding the real error
location. Try it.

try
{
// Some code that throws an exception
}
catch (Exception ex)
{
// some code that handles the exception
throw;
}
What has changed? Instead of "throw ex;", which will throw a new exception
and clear the stack trace, we have simply "throw;". If you don't specify the
exception, the throw statement will simply rethrow the very same exception
the catch statement caught. This will keep your stack trace intact, but
still allows you to put code in your catch blocks.
 
T

Tom Shelton

Greg said:
I thought I'd read somewhere that

Throw ex

behaved differently than just

Throw

all by itself?

Greg

As you pointed out, there is a difference in how the stack trace is affected
by doing a Throw vs. Throw ex. I use Throw when I need to do something
with an error of course, before I send it up the stack - but often times, I
really don't need to do anything with the exception except let it flow up
the stack... That's where the optional Catch comes in, since it
essentially preserves the stack, but lets you do any cleanup that needs to
be done.
 
J

Jay B. Harlow [MVP - Outlook]

Tom,
And with VB 2005 you can simplify it to:

| Using connection As SqlConnection = ... create the connection
| ' execute your stuff
| End Try


--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| wooster11 wrote:
|
| > Another good thing to put in your finally is your disposal or closing
| > of objects. Great for DB Connections.
| >
| > Try
| > dim SqlCn as SqlConnection..
| >
| > 'Excute your statement
| > Catch Ex as Exception
| > throw ex
| > Finally
| > if SqlCn.ConnectionState = Open Then SqlCn.Close
| > SqlCn.dispose
| > End Try
| >
| > This will always guarantee that you have a closed connection to your
| > database. This saves you from having to write that code twice, say in
| > the Try and in the Catch.
| > I use the Finally all the time.
| >
| > Derek Woo
|
| Just thought I'd point out - that the Catch in your example is really not
| necessary, since your just re-throwing the exception. I would probably
| just do this:
|
| Dim connection As SqlConnection = Nothing
|
| Try
| ' create the connection
| ' execute your stuff
| Finally
| ' dispose of your objects
| End Try
|
| The functional result is that the exception is thrown, just as yours does
| and your resources are still released. I do this all the time in my C#
| code :)
|
| --
| Tom Shelton [MVP]
 
T

Tom Shelton

Jay said:
Tom,
And with VB 2005 you can simplify it to:

| Using connection As SqlConnection = ... create the connection
| ' execute your stuff
| End Try

True... I do use using sometimes in C#, but I find that if there are a lot
of resources to be disposed, then it actually can be a hinderance to
readability if they are nested at multiple levels (since, you can only have
objects of the same type in the using statement):

using (SqlConnection connection = new ....)
{
using (SqlCommand command = new ....)
{
using (DataSet ds = new DataSet)
{
// blah
}
}
}

I can create multiple connections in the first block by putting them in a
comma separated list - but, I can't put both the connection and the command
in the same using statement... Hmmm, does VB2005 have this limitation? It
seems to me the only requirement is that the object should be of type
IDisposable (implement the interface :)....
 
C

Cor Ligthert [MVP]

Tom,

A dataset has AFAIK not any unmanaged resource, so in my opinon the extra
disposing of that has not much sense.

A point that I find a problem with the "using" in this situations is that
you cannot catch any updating error, not even a concurrency error, which
makes that in my eyes than there is needed, that globaly should be tested on
a wide range of error situations.

Just my opinon.

Cor
 
P

Phill. W

1. In a Finally clause, any Dim'ed variables will go out of scope
when the Try block finishes.

Other than it "looking" right to the human reader, can anyone suggest
why it does this? Limiting the scope to within the Try .. End Try
construct /as a whole/ would make so much more sense, especially
because you want to use Finally to clean things up, but can't because
a variable Dim'd within the Try goes out of scope when the code "hits"
the Catch (or Finally!) clause, and, therefore, no longer exists!

Yours, Perplexed,
Phill W.
 
J

Jay B. Harlow [MVP - Outlook]

Tom,
VB allows objects of different types:

Using connection As SqlConnection = ..., command As SqlCommand =
...., ds As New DataSet

End Using

I didn't realize C# had that restriction, what an odd restriction, although
I can see where it comes from.


FWIW: The above is equalivent to:

Using connection As SqlConnection = ...
Using command As SqlCommand = ...
Using ds As New DataSet

End Using
End Using
End Using

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Jay B. Harlow [MVP - Outlook] wrote:
|
| > Tom,
| > And with VB 2005 you can simplify it to:
| >
| > | Using connection As SqlConnection = ... create the connection
| > | ' execute your stuff
| > | End Try
| >
| >
|
| True... I do use using sometimes in C#, but I find that if there are a
lot
| of resources to be disposed, then it actually can be a hinderance to
| readability if they are nested at multiple levels (since, you can only
have
| objects of the same type in the using statement):
|
| using (SqlConnection connection = new ....)
| {
| using (SqlCommand command = new ....)
| {
| using (DataSet ds = new DataSet)
| {
| // blah
| }
| }
| }
|
| I can create multiple connections in the first block by putting them in a
| comma separated list - but, I can't put both the connection and the
command
| in the same using statement... Hmmm, does VB2005 have this limitation?
It
| seems to me the only requirement is that the object should be of type
| IDisposable (implement the interface :)....
|
| --
| Tom Shelton [MVP]
 
M

Mattias Sjögren

Tom,
True... I do use using sometimes in C#, but I find that if there are a lot
of resources to be disposed, then it actually can be a hinderance to
readability if they are nested at multiple levels (since, you can only have
objects of the same type in the using statement):

using (SqlConnection connection = new ....)
{
using (SqlCommand command = new ....)
{
using (DataSet ds = new DataSet)
{
// blah
}
}
}


Don't you have the same readability problem with nested try/catch
blocks?

BTW you don't have to indent each level

using (SqlConnection connection = new ....)
using (SqlCommand command = new ....)
using (DataSet ds = new DataSet)
{
// blah
}


Mattias
 
J

Jay B. Harlow [MVP - Outlook]

Mattias,
Ah! I was thinking there was a way...

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Tom,
|
| >True... I do use using sometimes in C#, but I find that if there are a
lot
| >of resources to be disposed, then it actually can be a hinderance to
| >readability if they are nested at multiple levels (since, you can only
have
| >objects of the same type in the using statement):
| >
| >using (SqlConnection connection = new ....)
| >{
| > using (SqlCommand command = new ....)
| > {
| > using (DataSet ds = new DataSet)
| > {
| > // blah
| > }
| > }
| >}
|
|
| Don't you have the same readability problem with nested try/catch
| blocks?
|
| BTW you don't have to indent each level
|
| using (SqlConnection connection = new ....)
| using (SqlCommand command = new ....)
| using (DataSet ds = new DataSet)
| {
| // blah
| }
|
|
| Mattias
|
| --
| Mattias Sjögren [MVP] mattias @ mvps.org
| http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
| Please reply only to the newsgroup.
 
H

Herfried K. Wagner [MVP]

Jay B. Harlow said:
| BTW you don't have to indent each level
|
| using (SqlConnection connection = new ....)
| using (SqlCommand command = new ....)
| using (DataSet ds = new DataSet)
| {
| // blah
| }

Ah! I was thinking there was a way...

Mhm... I still think the way chosen in VB.NET is better than those of C#.
The code above requires an additional indentation rule for the 'using'
statement.
 

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

Top