Thursday, February 15, 2007 9:44 PM
Here's a surprisingly little known tip for improving the stability of your .NET code. When you're debugging with Visual Studio, the default settings only allow the debugger to break on exceptions which are 'unhandled', meaning exceptions that usually bubble up to the top of the application stack, resulting in that really ugly "Unhandled Exception Occurred" dialog box.

I'm sure you're thinking that this is exactly what you want, right? Why would you care about exceptions that are caught? Well, let me pose this question to you...how many times in your codebase have you seen this...
try
{
MySubRoutine();
}
catch
{
// This method sometimes throw a null reference. I don't really
// know why but we'll just catch it here.
}
Did you catch what just happened here? The developer knew that the method call within the try block occasionally throws a null reference exception, so to be safe he just put the whole thing inside of a generic catch handler. Now, for the sake of argument we'll not talk about the fact that the developer isn't worrying about why the exception is being thrown, only that it is. The problem we're concerned with right now is the "catch" statement. This catch handler will definitely handle our null reference exception, no question there. But what happens if our rogue method generates a different type of error. Or what happens if one of our other methods throws an exception? Even worse yet, what happens if an unexpected exception occurs in Subroutine()? Well, what will likely happen is that the error will be quietly swept under the rug by the general exception handler and you'll spend hours trying to figure out why some button in the GUI 15 layers up seems to do absolutely nothing when you click it. Not that I'm speaking from experience or anything....
As you can imagine, the best defense for this is to just never catch general exceptions and, as a rule, to never catch an exception that you're not prepared to handle. However, in the real world this doesn't always happen. We inherit legacy code that has these general exception catches spread everywhere like a virus, we use third party open source libraries that do this inside of them and as a last ditch effort to keep exceptions from exiting the code we build APIs that have restrictions like "exceptions should never pass reach above this level". There is hope, however.
If you're debugging you can let Visual Studio tell you whenever an exception is thrown. This will allow you to break every time something goes wrong and make sure that what you think is happening in an exception handler really is happening in an exception handler. Under the "Debug" menu, click "Exceptions...". Odds are your "Thrown" column will be empty, click them on (you choose if you only want to look for certain types of exceptions or click on all of them) and watch the magic happen.

This can be a lifesaver when you're trying to figure out what's going on with a button that just seems to "die" or why that exception you're throwing in you business layer never seems to be properly handled but never seems to reach the top of the application either.
Try it once, you'll probably be amazed what's going wrong deep in the bowels of your application. You may have an application that seems perfectly stable and happy on the surface while underneath it all it's a tumultuous mess. Why do you care if the app seems fine in the big picture? Well, for one, those exceptions are expensive! Every time an exception is thrown thats one little more hiccup your app must endure. Some of these you hiccups you may have to live with, but you'd be surprised how easily others can be corrected. Are you getting a lot of FileNotFoundExceptions? Check if the file exists with File.Exists(string) before you try to use it? Getting a lot of NullReferenceExceptions? Do a quick (if object != null) before you start calling against it. You'll be amazed how easily you can eliminate some of the most common exceptions inside your app.