Exceptions in .NET– part II
In the previous post, we’ve started looking at how to use exception in .NET. Even though the CLR allows an instance of any type to be thrown for an exception (more about this in a future post), the truth is that all CLS compliant languages can only catch and throw Exception derived exceptions. That’s why in C# you can only throw and catch exceptions whose type is derived from Exception. The class exposes several interesting properties which you can use to get more information about an exception. The StackTrace property is (probably) one of the more important ones and you can use it from within a catch block to get a string which indicate the methods that were called that led up to the current exception. The following snippet tries to illustrate the use of this property:
And the next image shows the result at runtime:
As you can see, we end up getting the names of all the methods until the one where the exception was thrown. Typically, you won’t be using this info at runtime (ie, don’t show it to the final user!), but you should probably log it so that you can get more info about the exception when the phone starts ringing and someone starts complaining about a crash
If you’ve checked the docs for the Exception class, you’ve probably noticed the Message property. This property (which, btw, is read-only) contains info about the error and it should also explain how to fix the problem. Notice that this isn’t an error friendly message; in fact, it’s a technical message and this means that it shouldn’t be shown to the final user. There’s also a Data dictionary, where you can find a collection of key-value pairs with extra info about the exception (if you’re the middle-man, you can add-more information to this entry and re-throw it). The TargetSite and Source properties reference, respectively, the method that threw the exception (MethodBase instance) and the name of the assembly that generated the exception. Finally, there’s also an InnerException property which references the previous exception when the current one was raised when handling the first one (we’ll return to this topic in future posts).
If you look at the MSDN docs on exceptions, you’ll notice that there’s a long long hierarchy. Many of the predefined exceptions inherit from ApplicationException or SystemException. Originally, MS recommended that all new exceptions should expand one of these types. The idea was not bad since new applications exceptions should inherit from ApplicationException and system exceptions should expand the SystemException class. If that guideline had been followed, then it would be possible to have catch blocks which would handle all system exceptions or all applications exceptions. Unfortunately, not even MS followed its own guideline! This means that there are system/CLR exceptions which inherit directly from Exception and others which inherit (wtf?) from ApplicationException… Bottom line: these two classes are useless in the real world!
And that’s it for now. In the next post, I’ll present some considerations you should keep in mind when throwing an exception. Stay tuned for more.