LA.NET [EN]

Sep 09

Exceptions in .NET–part IV

Posted in .NET Basics C#      Comments Off on Exceptions in .NET–part IV

In one of the previous posts, I’ve mentioned that the CLR allows an instance of any type to be thrown for an exception (notice that this isn’t allowed by the CLS). In practice, this means that you should be able to throw ints or strings from CLR languages which allow you to write non-CLS compliant code. Since most people will use C# or VB.NET, they think that they’re only allowed to handle Exception derived exceptions and so they think that using the Exception type in a catch block is enough for getting all the exceptions. In other words, people think they would catch all the exceptions by writing this code:

try {
    //some code
}
catch(Exception ex) {
    //catches everything!
    //really???
}

And life was good until you needed to, say, consume some managed C++ code (which, for instance, interacted with some legacy code) that would end up throwing an exception which wasn’t derived from the base Exception type. There was a solution for this problem:

try {
    //some code
}
catch(Exception ex) {
    //catches everything!
    //really??? the answer is nop (<2.0)
}
catch {
    //but this does catch everything
    //(in all versions)
}

By using the catch all block, you are, in fact, catching all exceptions. In other words, the first catch block catches all the CLS compatible exceptions (ie, all Exception derived exceptions) and the second ends up catching all non-CLS compatible exceptions.

Now, the *GOOD NEWS*: you only need to worry about this if you’re running .NET 1.1. And that’s because MS recognized that it needed to “solve” this problem and introduced the RuntimeWrappedException class. Whenever you add the RuntimeCompatibilityAttribute to an assembly (which is done automatically by the C# compiler), all non-CLS compliant exceptions are wrapped by a RuntimeWrappedException object. This means that from 2.0 onwards, you can really catch all exceptions by using the 1st code snippet I’ve shown. Btw, if you want you can get the real thrown exception by accessing the WrappedException property (notice that it references an Object and not an exception).

And that’s it for now. Stay tuned for more.