13.4 .NET Exception Hierarchy

In C#, the exception-handling mechanism allows only objects of class Exception (namespace System) and its derived classes to be thrown and caught. Note, however, that C# programs may interact with software components written in other .NET languages (such as C++) that do not restrict exception types. The general catch clause can be used to catch such exceptions.

This section overviews several of the .NET Framework’s exception classes and focuses exclusively on exceptions that derive from class Exception. In addition, we discuss how to determine whether a particular method throws exceptions.

13.4.1 Class SystemException

Class Exception (namespace System) is the base class of .NET’s exception class hierarchy. An important derived class is SystemException. The CLR generates SystemExceptions. Many of these can be avoided if apps are coded properly. For example, if a program attempts to access an out-of-range array index, the CLR throws an exception of type Index-OutOfRangeException (a derived class of SystemException). Similarly, an exception occurs when a program uses a reference-type variable to call a method when the reference has a value of null. This causes a NullReferenceException (another derived class of SystemException). You saw earlier in this chapter that a DivideByZeroException occurs in integer division when a program attempts to divide by zero.

Other exceptions thrown by the CLR include OutOfMemoryException, StackOverflowException and ExecutionEngineException, which are thrown when something goes wrong that causes the CLR to become unstable. Sometimes such exceptions cannot even be caught. It’s best to simply log such exceptions (using a tool such as Apache’s log4nethttp://logging.apache.org/log4net/), then terminate your app.

A benefit of the exception class hierarchy is that a catch block can catch exceptions of a particular type or—because of the is-a relationship of inheritance—can use a base-class type to catch exceptions in a hierarchy of related exception types. For example, Section 13.3.2 discussed the catch block with no parameter, which catches exceptions of all types (including those that are not derived from Exception). A catch block that specifies a parameter of type Exception can catch all exceptions that derive from Exception, because Exception is the base class of all exception classes in the .NET Framework. The advantage of this approach is that the exception handler can access the caught exception’s information via the parameter in the catch. We’ll say more about accessing exception information in Section 13.7..

Using inheritance with exceptions enables a catch block to catch related exceptions using a concise notation. A set of exception handlers could catch each derived-class exception type individually, but catching the base-class exception type is more concise. However, this technique makes sense only if the handling behavior is the same for a base class and all derived classes. Otherwise, catch each derived-class exception individually.

Common Programming Error 13.2

The compiler issues an error if a catch block that catches a base-class exception is placed before a catch block for any of that class’s derived-class types. In this case, the base-class catch block would catch all base-class and derived-class exceptions, so the derived-class exception handler would never execute.

13.4.2 Which Exceptions Might a Method Throw?

How do we determine that an exception might occur in a program? For methods contained in the .NET Framework classes, read the detailed descriptions of the methods in the online documentation. If a method may throw an exception, its description contains a section called Exceptions that specifies the types of exceptions the method may throw and briefly describes what causes them. For an example, search for “int.Parse method” in the Visual Studio online documentation. The Exceptions section of this method’s web page indicates that method int.Parse throws three exception types:

  • ArgumentNullException,

  • FormatException, and

  • OverflowException

and describes the reasons for each. [Note: You also can find this information in the Object Browser described in Section 10.11..]

Software Engineering Observation 13.1

If a method may throw exceptions, statements that invoke the method directly or indirectly should be placed in try blocks, and those exceptions should be caught and handled.

It’s more difficult to determine when the CLR may throw exceptions. Such information appears in the C# Language Specification, which specifies cases in which exceptions are thrown. At time of writing, the C# specification has not yet been officially released by Microsoft. You can view an unofficial copy at:


https://github.com/ljw1004/csharpspec/blob/gh-pages/README.md
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset