共用方式為


Many Questions: general catch clause

I’m back from my course on Software Design. Now that we are starting to think about the version of C# after VS 2005 we are shining a bright light on all the ways the current compiler codebase could be better. This is the fun part of the product cycle where you get to really dig in and reorganize your code. Fun stuff!

I hope everyone had a good weekend. I spent the weekend out in the San Juan Islands. A bunch of us went out to celebrate Tim’s bachelor party. I’m mostly recovered from the hangover – so I hope I can keep it together for this week’s question:

In C# only objects derived from System.Exception can be thrown, so why allow general catch clauses? Isn’t that just the same as catch (System.Exception)?

C# allows specifying two kinds of catch clauses – specific catch clauses, and general catch clauses. Specific catch clauses specify the type of exception to be caught. Exceptions which are not of the specified type are ignored by the specific catch clause.

        try

        {

            using (StreamReader reader = new StreamReader(fileName))

            {

                char[] text = reader.ReadToEnd().ToCharArray();

                ...

            }

        }

        catch (IOException e)

        {

            Console.WriteLine("Error reading from file '{0}' : '{1}'",

                              fileName, e.Message);

        }

This example demonstrates a good guideline when catching exceptions – only catch exceptions that you expect, and in general catch the most specific set of exceptions possible. In this case the System.IO.IOException is an expected result of attempting to read a file, so catching it is reasonable.

In contrast, general catch clauses don’t name a type. They catch all thrown objects. The general catch clause is useful in the (hopefully rare) occasions when you need to catch everything. However, a specific catch clause which catches System.Exception is guaranteed to catch everything that can be thrown by C# code. So why add the general form of the catch clause?

The subtle difference is that although catch System.Exception will catch everything that C# code can throw, it doesn’t catch everything that the CLR can throw. In the CLR, any object can be thrown – even objects not derived from System.Exception. That’s right, in IL or C++ you can throw the string “hello”, or the integer 5 just as easily as you can throw a new System.Exception()!

The general catch clause was added to C# so that code which interoperates with non-C# code can catch anything that can be thrown in the CLR. One of the benefits of C# running on the CLR is that it allows C# code to interoperate easily with other CLR languages, however this example shows that this feature has some drawbacks as well. Needless to say, the fact that a string can be thrown is a subtlety that most C# programmers are not aware of, and it’s exactly those kinds of subtleties that can lead to unexpected bugs.

Well, this was all a warm up to talk about a new feature that was added to the CLR and C# in VS2005 to help address the mismatch. Unfortunately its getting late and I need to grab some dinner. I’ll have to save that for my next post …

Peter

C# Guy

Comments