Update Looks like I shouldn't have taken what we all know and tested it. http://www.yoda.arachsys.com/csharp/exceptions.html However at least Jon seems to come to the same final argument. There are places for exceptions and places where you avoid them.
Now we all know that exceptions are slower than return codes
[see above]. There is a considerable degree of debate about their usage, with some people saying you shouldn't ever, some people marking up everything as an exception, and many more sensible people in the middle.
Personally I think that exceptions are very useful for exceptional circumstances. i.e. Don't use them often, and they pay for themselves. If, for example, I can return an empty collection or a null, I do. This means I have to program defensively1 in calling code to avoid null refs and so on, but if you forget then you simply generate the null ref exception you would have thrown anyway. (Ok this is a simplification, but you get the idea).
Anyway more information than you ever wanted about exceptions is available here in the blog of Chris Brumme, one of the CLR developers.
Consider the try/catch on this example. NOTE this is so WRONG
public SomeMethod(...)
{
try
{
....
}
catch (Exception ex)
{
throw(ex);
}
finally
{}
}
The only result of the try..catch..finally code here is to slow down the exception handling.
- throw is expensive in time as it has to crawl the stack 1 and detect where to drop out for catches.
- catch and doing nothing with the caught exception simply adds to that time
- throw; would have resumed the original list of catches derived from the stack, BUT throw(ex); starts the whole process again, effectively doubling the time for the exception AND wipes out the true location of the original exception.
1 Actually some of the things that happen when you throw an exception (from http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx - this is really detailed!)
- Grab a stack trace by interpreting metadata emitted by the compiler to guide our stack unwind.
- Run through a chain of handlers up the stack, calling each handler twice.
- Compensate for mismatches between SEH, C++ and managed exceptions.
- Allocate a managed Exception instance and run its constructor. Most likely, this involves looking up resources for the various error messages.
- Probably take a trip through the OS kernel. Often take a hardware exception.
- Notify any attached debuggers, profilers, vectored exception handlers and other interested parties.
1.
http://en.wikipedia.org/wiki/Defensive_programming defines 'Defensive programming' from a security point of view. I always take a wider view. Don't trust anything, check return values, before using them. If you read between the lines then I agree with the intent, if not the definition