Exception Handling Changes in C# 2.0
Charlie Calvert asked me to write some C#posts for MSDN C# Developer Center. This article is the first of aseries about the changes from C# 1.0 to C# 2.0. By this I don't meanenhancements (generics, partial classes, etc), but items that wouldeither cause compile errors, create warnings, or change (presumablyimprove) behavior. I haven't seen much of a comprehensive listing ofthese changes so I decided to try my hand at coming up with one. Intoday's post I am going to talk about a change in exception handling.
Consider the following code listing:
using System;
class Program
{
static void Main()
{
try
{
Console.WriteLine(
"Hello. My name is Inigo Montoya.");
}
catch(Exception )
{
// .
}
catch
{
Console.WriteLine("UNEXPECTED EXCEPTION");
}
}
}
In C# 1.0, this code was perfectly valid. However, in C# 2.0 it results in a warning. Why is that?
An empty catch block (catch{ . }), compilesdown to CIL code that is the equivalent of catch(object ){ . }. Inother words, an empty catch block in C# is a catch block for any andall types that are thrown as exceptions. (Interestingly, C# doesn'tallow you to explicitly code catch(object ){ . }. Therefore, there isno means of catching a non-System.Exception-derived exception and havethe exception instance to scrutinize.)
It is perhaps surprising that catch(object ){. } is needed because C# doesn't allow you to throw an exception thatdoesn't derive from System.Exception. However, the same restrictiondoes not apply to other languages. C++, for example, can throw anobject of any type (whether derived from System.Exception or not). As aresult, in C# 1.0, the only way to ensure that all exceptions werecaught was to include an empty catch block.
In C# 2.0 the rules improved. Although it isstill possible for other languages to throw exceptions of any type, theCLR will wrap all exceptions that do not derive from System.Exceptioninto a System.Runtime.CompilerServices.RuntimeWrappedException object,which does derive from System.Exception. In other words, allexceptions, whether System.Exception-derived or not when they arethrown, will be caught in C# 2.0 code by a catch(Exception ){ . }block.
Therefore, if you follow a catch(Exception ){. } block by an empty exception block (as shown in the initial codelisting), the empty exception block will never execute. All exceptionswill be wrapped in the RuntimeWrappedException if they do not derivefrom System.Exception already and therefore be caught bycatch(Exception ){ . }.
One more thing to note: If you wish your codeto behave as it did with C# 1.0 in this area, you can add theRuntimeCompatibility assembly attribute as in:
[assembly:System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = false)]
This will no longer produce the warning sinceit will also turn off the new CLR 2.0 behavior in whichnon-System.Exception-derived exceptions are wrapped withRuntimeWrappedException.




12. Sep, 2007 by 







No comments yet... Be the first to leave a reply!