Exception Handling

Exception Handling

When something goes wrong during the execution of an application, the .NET Framework responds by throwing an exception. Some exceptions are thrown by the CLR. For example, if an application attempts to cast an object to a type that it s not, the CLR throws an exception. Others are thrown by the FCL for example, when an application attempts to open a nonexistent file. The types of exceptions that the .NET Framework throws are legion, so an application that targets the framework better be prepared to handle them.

The beauty of exceptions in the world of managed code is that they re an intrinsic part of the .NET Framework. In the past, languages (and even individual language compilers) have used proprietary means to throw and handle exceptions. You couldn t throw an exception in Visual Basic and catch it in C++. You couldn t even throw an exception in a function compiled with one C++ compiler and catch it in a function compiled with another. Not so in a managed application. The CLR defines how exceptions are thrown and how they re handled. You can throw an exception in any language and catch it in any other. You can even throw exceptions across machines. And to top it off, languages such as C# and Visual Basic .NET make exception handling extraordinarily easy.

Catching Exceptions

C# uses four keywords to expose the CLR s exception handling mechanism: try, catch, finally, and throw. The general idea is to enclose code that might throw an exception in a try block and to include exception handlers in a catch block. Here s an example:

try { Hashtable table = new Hashtable (); table.Add ("First", 1); string entry = (string) table["First"]; // Retrieve 1 and cast it } catch (InvalidCastException e) { Console.WriteLine (e.Message); }

An integer is not a string, so attempting to cast it to one will generate an InvalidCastException. That will activate the InvalidCastException handler, which in this example writes the message encapsulated in the exception object to the console. To write a more generic catch handler that catches any exception thrown by the framework, specify Exception as the exception type:

catch (Exception e) { ... }

And to respond differently to different types of exceptions, simply include a catch handler for each type you re interested in:

try { ... } catch (InvalidCastException e) { ... } catch (FileNotFoundException e) { ... } catch (Exception e) { ... }

The CLR calls the handler that most closely matches the type of exception thrown. In this example, an InvalidCastException or FileNotFoundException vectors execution to one of the first two catch handlers. Any other FCL exception type will activate the final handler. Notice that you don t have to dispose of the Exception objects you catch because the garbage collector disposes of them for you.

All of the exception types defined in the FCL derive directly or indirectly from System.Exception, which defines a base set of properties common to FCL exception types. Thanks to System.Exception, for example, all FCL exception classes contain a Message property, which holds an error message describing what went wrong, and a StackTrace property, which details the call chain leading up to the exception. Derivative classes frequently add properties of their own. For instance, FileNotFoundException includes a FileName property that reveals what file caused the exception.

The FCL defines dozens of different exception classes. They re not defined in any one namespace but are spread throughout the FCL s roughly 100 namespaces. To help you get a handle on the different types of exceptions you re liable to encounter, the following table lists some of the most common exception types.

Common FCL Exception Classes

Class

Thrown When

ArgumentNullException

A null reference is illicitly passed as an argument

ArgumentOutOfRangeException

An argument is invalid (out of range)

DivideByZeroException

An attempt is made to divide by 0

IndexOutOfRangeException

An invalid array index is used

InvalidCastException

A type is cast to a type it s not

NullReferenceException

A null reference is dereferenced

OutOfMemoryException

A memory allocation fails because of a lack of memory

WebException

An error occurs during an HTTP request

As in C++, exception handlers can be nested. If method A calls method B and method B throws an exception, the exception handler in method B is called provided a suitable handler exists. If method B lacks a handler for the type of exception that was thrown, the CLR looks for one in method A. If A too lacks a matching exception handler, the exception bubbles upward to the method that called A, then to the method that called the method that called A, and so on.

What does the .NET Framework do with unhandled exceptions? It depends on the application type. When a console application suffers an uncaught exception, the framework terminates the application and writes an error message to the console window. If the application is a Windows Forms application, the framework alerts the user with a message box. For a Web Forms application, the framework displays an error page. Generally speaking, it s far preferable to anticipate exceptions and handle them gracefully than allow your users to witness an unhandled exception.

Guaranteeing Execution

Code in a finally block is guaranteed to execute, whether an exception is thrown or not. The finally keyword really comes in handy when you re dealing with those pesky classes that wrap file handles and other unmanaged resources. If you write code like

File file = new File ("Readme.txt"); . . . file.Close ();

you ve left a file open if an exception occurs after the file is opened but before Close is called. But if you structure your code this way, you re safe:

File file = null; try { file = new File ("Readme.txt"); . . . } catch (FileNotFoundException e) { Console.WriteLine (e.Message); } finally { if (file != null) file.Close (); }

Now Close is called regardless of whether an exception is thrown.Be aware that try blocks accompanied by finally blocks do not have to have catch blocks. In the previous example, suppose you want to make sure the file is closed, but you don t really care to handle the exception yourself; you d rather leave that to a method higher up the call stack. Here s how to go about it:

File file = null; try { file = new File ("Readme.txt"); . . . } finally { if (file != null) file.Close (); }

This code is perfectly legitimate and in fact demonstrates the proper way to respond to an exception that is best handled by the caller rather than the callee. Class library authors in particular should be diligent about not eating exceptions that callers should be aware of.

Throwing Exceptions

Applications can throw exceptions as well as catch them. Look again at the Width and Height properties in the Rectangle class presented earlier in this chapter. If a user of that class passes in an invalid Width or Height value, the set accessor throws an exception. You can also rethrow exceptions thrown to you by using the throw keyword with no arguments.

You can use throw to throw exception types defined in the FCL, and you can use it to throw custom exception types that you define. Although it s perfectly legal to derive custom exception types from System.Exception (and even to declare exception classes that derive directly from System.Object), developers are encouraged to derive from System.ApplicationException instead, primarily because doing so enables applications to distinguish between exceptions thrown by the framework and exceptions thrown by user code.

That s the theory, anyway. The reality is that the FCL derives some of its own exception classes from ApplicationException, meaning that having ApplicationException as a base type is not a reliable indicator that the exception wasn t thrown by the framework. Don t believe any documentation that says otherwise.



Programming Microsoft  .NET
Applied MicrosoftNET Framework Programming in Microsoft Visual BasicNET
ISBN: B000MUD834
EAN: N/A
Year: 2002
Pages: 101

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net