Your code down there looks like you are on teh right
track. Here's a few general pointers....
1) Don't trap an exception just to trap it. If you
catch System.Exception all over the place, without more
specific handlers before it, you are really just leaving
yourself out in the dark. For instance, if a Database
connection fails, wouldn't you want your program to react
differently than if you had an out of memory exception?
Obviously you would.
2) If you keep your code very modular, ie used in small
blocks instead of large routines, it's fairly easy to
know all of the exceptions that could occur and react
accordingly. As such, keep things modular and wrap
things with a large potential for error in blocks.
Someone posted last week that they seldom wrap more than
a single line in a block of code. I highly agree with
this approach. Similarly, If you have a snippet of code
that opens a DB connection for example (a risky endeavor
b/c regardless of code, a available DB connection
determines success or failure, and the DB may not always
be up or available), and say it's a SQL server you are
connecting to...you can't possibly get an INdexOutofRange
exception or much other than a SQLException. So you can
trap a sqlexception and either try again, wait and try
again, notify the caller that the connection won't open
and the program can't do anything until such a time as it
can etc. My point is mainly that you should try to keep
your blocks small an trap very specific exceptions.
3) You are already doing it, but remember to go from
specific to general exceptions if you have multiple
handlers, not the other way around. If you trapped
System.Exception first, it will always execute there even
if you have a more specific handler underneath it.
4) Make sure that you actually handle the exception. Do
something with it, try a plan b, c, d etc or at a
minimum, notify the calling application. Depending on
frequency of the exceptions, you can write to the event
logs or log it in a DB or message queue for later
reference.
5) To whatever extent possible, don't intentionally
throw exceptions that will happen frequently and rely on
your handlers to deal with it. I've seen some code for
instance where the developer knew that every time some
code execute, it would throw an exception and he was fine
with it because he had a handler that just did nothing,
but the program appeared to be working fine. The
problem? It was an index out of range exception and he
was iterating through an arraylist. Clearly using -1 on
the top index would have fixed this. This is obviously
an extreme example, but trapping exceptions isn't free,
and while it's not the costliest resource hog, it does
take away resources that may (and almost certainlly
will ) be scarce on someone's machine.
5) Make sure that if something fails, everything else
that depended on its success knows of the failure.
Otherwise, you'll probably end up with both logic and
functionality problems.
6) Let the caller handle most of the exceptions. THis
is something that needs some clarification, but every
block of code doesn't need an exception handler. So if I
have a block in main that makes a bunch of calls, it may
be ok at this level to trap system exception, after all,
if I get an outofmemory exception, this is the
appropriate place to deal with it. HOwever, if I'm
sending a query and I've trapped the possible
SqlExceptions, I don't want to the called code to trap
generic exceptions do i? No, b/c I can't possibly know
every thing that could happen there...and If I don't know
everything that can happen, how can I respond to
everything? This is where exception logs come in very
handy if you write to the system error logs or create
your own. ALso, such logging cna let you know if you
have a flaw in your code that's causing frequent problems.
7) Use Finally like a fanatic. Remember however, that
the finally block ALWAYS executes,regardless of an
exception or not. It's a create place to close open
connections and dispose of objectst thta you are finished
with.
8) NEVER use On Error Resume and unless you have a
Really good reason, never trap something and totally
ignore it. On Error Resume is from h### and all it does
behind the scenes is wrap every single line executed in a
System.Exception try catch block behind the scenes. It
definetely eats resources and it can obscure problems
that need to be addressed.
9) Write your own exceptions. Since you can inherit
from System.Exception, you can create very very specific
exceptions that aren't included in the core library.
Granted, some will argue that you can simply raise custom
events to obviate the need for this, but I don't think
they are mutually exclusive. I have an event in a web app
for instace called AttemptedSA which is raised if someone
tries to connect to the db with the SA password (which is
disabled, but lets me know that someone is trying to hack
the machine). I have a class of exceptions called
HackAttemptExceptions that I deal with by firing them
into a message queue and ultimately emailing me of the
attempt and writing to a Socket that I have connected to
a listener so I can see it real time from many places in
my office. Different hack attemps require different
responses, but I use an event to throw the exception and
respond accordingly. Nothing in the System.Exception
classes is made to warn of an attempted log-in with SA
b/c many times people want to log-in with SA. In my
specific company, we don't so custom exceptions can
really come in handy here. Once you start using them,
you'll invariably come up with many situations where you
realize how helpful they cna be.
If you haven't picked it up already, Jeffrey Richter's
book on the .NET Framework by MS Press has a Really
excellent discussion on the subject, and IMHO, that book
would still be a bargain if it cost 3 times what it
does. I've learned a ton from that book alone.
Well, I hope this helps.
Good Luck,
Bill
W.G. Ryan
(e-mail address removed)
www.knowdotnet.com