C# .NET Exception Handling

This post is based on Chapter 7 of Andrew Troelsen’s “Pro C# 2008 and the .Net Platform” available from Apress.

So, we’ll assume you know the basics, and just quickly cover a few important gotchas from Mr. Troelsen’s most excellent book.

Some terminology:

  • Bugs: programmer errors (sorry).
  • User errors: users inputting invalid data, and generally dicking around with things.
    Arguably most of these are bugs,  as you should always (and sooner or later will come to) anticipate that your users will dick around with stuff in the most wonderful and fantastic ways possible.
  • Exceptions: Program errors caused by “Exceptional circumstances”. So perhaps your database server blows up, or maybe somone trips over the power cable to the internet.
    Main point is that these are unforeseen force majeure type events, and these are the only true type of exceptions, everything else, unfortunately are bugs – however, quite often the CLR will respond to a bug by raising an exception – thou, if you’re really lucky (and you will be) the bug will result in incorrect data or responses.

The System.Exception Base Class

This implements two interfaces:
System.Runtime.InteropServices._Exception means that unmanaged code bases like COM applications are able to process the Exception.
System.Runtime.Serialization.ISerializable – means you can serialise the exception to a file or similar – more on this later.

Some useful properties of the Exception base class are:

  • Data – this is a IDictionary collection of object key/value pairs that allows you to forward state data to your handling logic (useful for debugging). This is empty by default
  • InnerException – contains info on any exceptions that occurred prior to the current.
    These are forwarded by catching one, and creating a new where you pass the current into the constructor.
    Note that you can loop through these in your handling code using a while != null check (and re-point your reference to the inner, you know what I mean!).
  • Message – this is a short description of the error, you can hand this to the constructor of any exception you choose to throw yourself.
  • Source – this is the assembly that threw the Exception.
  • Stacktrace – this is a trace on the call stack that lead to the exception, note that you read this top down if you want to start with where things went wrong.
  • TargetSite – this is the method that caused the offending operation. Note that this is a System.Reflection.MethodBase object.
  • ToString() – is overridden to give you the Message, Class name and stacktrace – and what’s more it will recurse through the innerexception and call ToString() on each – so you end up with the original exception first, and any subsequent in ascending order.
    Note however that this does miss out a few properties  – so you might not want to rely (solely) on this for any logging.

Note also that you method and class documentation markup allows you to specify the possible exception that should be handled (will show up in intellisense).

Handling and Throwing Exceptions

When should you throw exceptions? I’ve always wondered… and when should you catch and rethrow…?

Well – as a rule of thumb, only throw exceptions when something serious and terminal has gone wrong. If you cannot find a file you need, if you cannot connect to the DB server… or whatever – though most of these will already throw exceptions.
If you can catch and handle a condition, and communicate this to your caller in some sensible way, this is always preferable.

If you do throw exception, note that you should  hand any prior exceptions into the constructor.  You can then set most of the properties mentioned above on your new exception, including a helplink, might come in handy some day, who knows.  Also, any state data that might be useful for debugging can be added to the Data property – like parameter values or a DateTime.Now timestamp. Make sure you null check though!
However – generally you are better of constructing a strongly typed Exception class of your own rather than relying on the Data property.

In fact – never get too clever or complicated in your exception handling – worst thing you can have, is buggy exception handling. Just red ear embarrassing stuff!
Try and keep things simple – the main aim should be to inform the user in a sensible way, and then make sure you log as much as you can.. and make sure you at some point end up with a fail safe catch clause, that if all else fails simply informs the user that x went wrong trying to y. Alwyas avoid (even as a last resort) showing your users the full exception with stacktrace etc, it’s not professional and there are certain security issues (they’re minor, but essentially you could be showing a malicious user part of your code (from the stacktrace) and also inform them of the sorftware platform and version used).

When handling exceptions always try and catch the most specific first (use your intellisense and hover over methods to get possible exceptions).

Note that you can use an empty throw; call to simply rethrow the original exception without any modifications (so the original target will be preserved).

Note that you can use an empty catch{} statement to handle all exceptions (so similar to catching the base System.Exception class – however you catch nothing, but handle everything).

Building Strongly Typed Exceptions

First of all realise that we have system level exception, which inherit from System.SystemException – these are thrown by the .NET runtime, and you should not inherit from this class.

Then we have application level exception, inheriting from System.ApplicationException – to roll your own, inherit from this.

Note that convention is that all exception classes should end in, you guessed it: Exception.

So, just when exactly should you build your own custom exceptions?
Generally, you should do this when the exceptions is tightly coupled to the class you are working with (i.e. none of the existing exception classes makes sense or meet your requirements). A sign of this can be that you find yourself throwing a new ApplicationException – which on the other hand is too general, and not best practise, so – if nothing more specific meets your needs, roll your own!

If you do build your own Exception type (i.e. class) – make sure you use constructor forwarding to avoid code redundancy. Also, if you want to go all the way and follow Microsoft best practises (which of course you do), your custom exception class  should meet the following checklist:

  • Derive from ApplicationException
  • Marked with the Serializable attribute, and define a constructor to handle serialization of your type (more on this later)
  • Define a default constructor, a constructor that sets your Message property and finally a constructor that handles any inner exceptions.

Note that there is a code snippet (ctrl+k+x) in VS2008 for this  – which will give you a class stubs for all the above.

And Finally… the finally block

Had to do that didn’t I?
Only thing to remember here is that this is always executed, exception or no exception. And it’s a great place to tidy up things and close connections – however, do note that you cannot return control from your method (i.e. return…; ) from within a finally block.

System.Runtime.InteropServices._Exceptio
Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: