System.Exception: The mother of all exceptions

When the exception is thrown, execution flow is transferred to the catch block that is capable of handling the exception thus skipping the rest of the code below the line that threw the exception in the try block. The code in the catch block handles the exception appropriately and then execution flow moves to the code in the finally block.

7.4 System.Exception: The mother of all exceptions

Let’s take some time to look at the parent exception class in the .NET framework – the System.Exception class. All exception classes are directly or indirectly derived from this class. To see how to put this class to use, let’s quickly dive into a simple example where we can see all the exception handling constructs try , catch , throw , and finally in action. To start with fire up your favorite text editor my personal favorite is Notepad and type in the following code: Code listing in C using System; class HelloWorld { static void Mainstring[] args { try { Console.WriteLineHere we go...; Throw an exception throw new ExceptionOops . Your computer is on fire ; This line should never execute Console.WriteLineHow on earth did I get called ?; } catchSystem.Exception ex { Display the error message Console.WriteLineCaught exception : {0}, ex.Message; } finally { This should always get called Console.WriteLineIn finally; } } } Code listing in VB.NET Imports System Module HelloWorld The Main entry point of the application Sub Main Try Console.WriteLineHere we go... Throw an exception Throw New ExceptionOops . Your computer is on fire This line should never execute Console.WriteLineHow on earth did I get called ? Catch ex As Exception Console.WriteLineCaught exception : {0}, ex.Message Finally This should always get called Console.WriteLineIn finally End Try End Sub End Module So what we have here is a try block that throws an exception by creating an instance of the System.Exception class with a descriptive error message. There’s a catch block to handle exceptions of type System.Exception . The code in the catch block just displays the error message. Finally, the finally block no pun intended logs a message that confirms that it did execute even though an error was thrown. So let’s save this program to a file named HelloWorld with the appropriate extension depending on the language you are using - .cs or .vb, the Hello World of Exception handling if you will. To compile the C program, type in the following command from the DOS command line: csc target:exe HelloWorld.cs To compile the VB.NET program, type in the following command from the DOS command line: vbc target:exe HelloWorld.vb This will generate an executable named HelloWorld.exe . Run the program and here’s the output that you get: Here we go... Caught exception : Oops . Your computer is on fire In finally You’ll notice that the exception that was thrown is caught by the catch block and that any statements that occur in the try block below the line that threw the exception are not executed. Notice that when you compiled the program in C, the compiler generated the following warning: Warning in C HelloWorld.cs16,4: warning CS0162: Unreachable code detected This goes to show that the C compiler detected that the statement that follows the throw statement in the try block would never get executed because of the exception that was thrown, and thus warned us of unreachable code. We saw how the Message property of the System.Exception class can be used to get a descriptive error message for the exception. Similarly, let’s examine the some of the other important properties of the System.Exception class. Let’s start by modifying the catch block in example that we just saw with the following code: Code listing in C Replace the catch block in our previous example with the following code catchSystem.Exception ex { Console.WriteLineCaught exception : {0}, ex.Message; Console.WriteLineSource of the exception is : {0}, ex.Source; Console.WriteLineMethod that threw the exception is : {0}, ex.TargetSite.Name; Console.WriteLineInfo on this exception is available at : {0}, ex.HelpLink; Console.WriteLineStack trace of this exception: {0}, ex.StackTrace; } Code listing in VB.NET Replace the catch block in our previous example with the following code Catch ex As Exception Console.WriteLineCaught exception : {0}, ex.Message Console.WriteLineSource of the exception is : {0}, ex.Source Console.WriteLineMethod that threw the exception is : {0}, _ ex.TargetSite.Name Console.WriteLineInfo on this exception is available at: {0},ex.HelpLink Console.WriteLineStack trace of this exception: {0},ex.StackTrace Finally Rest of the code goes here . . . Compile and run the application and observe the output that you get: Output in C Here we go... Caught exception : Oops . Your computer is on fire Source of the exception is : HelloWorld Method that threw the exception is : Main Info on this exception is available at: Stack trace of this exception: at HelloWorld.MainString[] args In finally Output in VB.NET Here we go... Caught exception : Oops . Your computer is on fire Source of the exception is : HelloWorld Method that threw the exception is : Main Info on this exception is available at: Stack trace of this exception: at HelloWorld.Main In finally You’ll notice that you can get rich information on the exception that occurred including details on the application and the method that threw the exception through the Source and TargetSite properties respectively and a complete stack trace of the exception in a string representation using the StackTrace property. Note that if you compile your code in debug mode i.e. using the debug+ compiler option, the Source and StackTrace properties will show you the actual line numbers in the source code which raised the exception. You’ll notice that the HelpLink property, which is supposed to provide a link to help file or a URL that contains information on the exception that occurred, does not seem to return anything. This is because we did not set this property when throwing the exception. To do that you simply need to set the HelpLink property before raising the exception. Here’s a snippet of code that shows how you can do that: Code listing in C Create an Exception Exception exception = new ExceptionOops . Your computer is on fire ; Set the help file details exception.HelpLink = http:www.someurl.comhelpComputerOnFireHelp.html; Throw the exception throw exception; Code listing in VB.NET Create an Exception Dim excep as Exception = New ExceptionOops . Your computer is on fire Set the help file details excep.HelpLink = http:www.someurl.comhelpComputerOnFireHelp.html Throw the exception Throw excep Replacing the statement that throws the exception with the above 3 statements in our example application, compiling it, and running it will now yield the following results: Output in C Here we go... Caught exception : Oops . Your computer is on fire Source of the exception is : HelloWorld Method that threw the exception is : Main Info on this exception is available at: http:www.someurl.comhelpComputerOnFireHelp.html Stack trace of this exception: at HelloWorld.MainString[] args In finally Output in VB.NET Here we go... Caught exception : Oops . Your computer is on fire Source of the exception is : HelloWorld Method that threw the exception is : Main Info on this exception is available at: http:www.someurl.comhelpComputerOnFireHelp.html Stack trace of this exception: at HelloWorld.Main In finally There’s one other thing that you need to be aware of - The notion of an inner exception, that you can access using the InnerException property of the main exception. So what exactly is an inner exception? . Assume that you have a nice cool stock portal that allows customers to manage their stocks and investments. The stock portal uses a database to store data on customers and their portfolio. Now, let’s say that you encounter a database specific error in your application. The last thing that you want to do is to display some cryptic ADO or OLEDB messages in your web pages that your customers don’t care a hang about. In such cases, you might have a catch handler to catch database specific exceptions. What this catch handler would essentially do is to create a more generic exception that is application specific maybe an exception that tells the user that the site encountered an internal error and would assign the database specific exception to the application-specific exception’s InnerException property. The catch handler then re-throws this application-specific exception expecting that one of the outer catch blocks will handle the generic exception. We’ll see how to re-throw exceptions in the section, Nesting trycatchfinally blocks and re-throwing exceptions . Inner exceptions are very useful when you are dealing with exceptions that occur in multiple tiers of typical enterprise applications. This allows you to envelope specific exceptions that actually caused the error into more application-specific exception types, and at the same time allows clients to determine the specific exception type InnerException that caused the application-specific exception to be thrown. Now since we know more about the System.Exception class, let’s take a look at the types of exceptions and how they can be classified. Broadly, there are two types of exceptions: System exceptions Exception classes derived from System.SystemException Application exceptions Exception classes derived from System.ApplicationException Understanding system exceptions: System exceptions are pre-defined exceptions that ship with the .NET framework class library. For example, the System.IO.IOException class, which is predefined exception in the framework class library for handling inputoutput related errors on files, streams etc., is derived from the System.SystemException class. There are tons of other similar predefined system exception classes that are defined and used in the FCL and which can be used in our applications as well. Let’s take a look at a quick example on how to handle system exceptions in your application. We’ll use the System.DivideByZeroException as our guinea pig here and simulate a situation where the FCL throws this exception. We’ll handle this error and report the error to the user. Fire up Notepad, and type in the following code: Code listing in C using System; class MyDecimalDivider { static void Mainstring[] args { try { Trigger a divide by zero exception Decimal dResult = Decimal.Divide5,0; We should never get here Console.WriteLineResult is : {0}, dResult; } catchDivideByZeroException exDivByZero { Console.WriteLineCaught Divide By Zero exception: {0}, exDivByZero.Message; } catchException ex { Console.WriteLineCaught exception: {0},ex.Message; } finally { Should always execute Console.WriteLineIn finally; } } } Code listing in VB.NET Imports System Module MyDecimalDivider Sub Main Try Trigger a divide by zero exception Dim dResult as Decimal = Decimal.Divide5,0 We should never get here Console.WriteLineResult is : {0}, dResult Catch exDivByZero As DivideByZeroException Console.WriteLineCaught Divide By Zero exception: {0}, _ exDivByZero.Message Catch ex As Exception Console.WriteLineCaught exception: {0}, ex.Message Finally Should always execute Console.WriteLineIn finally End Try End Sub End Module So essentially, what we’re doing here is simulating a DivideByZeroException by calling the Divide static method of the System.Decimal class and passing in a value of 0 for the divisor. A quick look at the documentation for the Divide method will tell you that the method throws a DivideByZeroException when attempting to divide by 0. So we’re setting up a catch block to handle exceptions of type System.DivideByZeroException . Save the file to MyDecimalDivider with the appropriate extension .cs or .vb depending on the language that you are using . Let’s get down to compiling the application. Type the following command from the DOS command prompt: Compiling in C csc target:exe MyDecimalDivider.cs Compiling in VB.NET vbc target:exe MyDecimalDivider.vb That takes care of generating an executable file named MyDecimalDivider.exe . Run the program and observe the output: Caught Divide By Zero exception: Attempted to divide by zero. In finally There we go. As seen above, the catch handler for the DivideByZeroException took care of catching the exception that was raised when we attempted to divide 5 by 0. The System.DivideByZeroException is just one of the many predefined system exception classes in the FCL. For a complete list of the other system exception classes, swing by to: http:msdn.microsoft.comlibraryen- uscprefhtmlfrlrfsystemsystemexceptionclasshierarchy.asp Ordering catch handlers to filter exceptions: Notice that we also have another catch block that handles the generic System.Exception . If none of the other catch handlers can handle an exception raised, the System.Exception catch handler will always lend a helping hand in catching and handling the exception, since the rest of the exception types are derived from this class. So that brings us to another thing that you need to remember - If you do not have a catch handler to handle a specific exception type, say SomeException , but do have a catch hander that can handle a type that is a super class of SomeException , then the catch handler associated with that super class will be asked to handle the exception. In our example, even if we did not have the catch handler for the System.DivideByZeroException , the catch handler for the System.Exception would have been able to handle the exception, since System.DivideByZeroException inherits from System.ArithmeticException , which in turn derives from System.SystemException and hence System.Exception . Keeping this in mind, it is important to understand that the order in which you place your catch handlers plays a key role in determining the catch handler that will eventually handle your exceptions. As a general rule, always place exception types of more derived classes in an exception class hierarchy higher up in the chain and place base class super class exception types lower down in the chain. To illustrate this, let’s slightly modify the earlier divide by zero example and note down a few observations: Modify the MyDecimalDivider.cs code sample as shown below to introduce a catch handler for the System.ArithmeticException , which is the immediate base class of the System.DivideByZeroException and place that catch handler above the catch handler that handles the DivideByZeroException : Code listing in C using System; class MyDecimalDivider { static void Mainstring[] args { try { Trigger a divide by zero exception Decimal dResult = Decimal.Divide5,0; We should never get here Console.WriteLineResult is : {0}, dResult; } catchArithmeticException exArithmetic { Console.WriteLineCaught Arithmetic exception: {0}, exArithmetic.Message; } catchDivideByZeroException exDivByZero { Console.WriteLineCaught Divide By Zero exception: {0}, exDivByZero.Message; } catchException ex { Console.WriteLineCaught exception: {0}, ex.Message; } finally { Should always execute Console.WriteLineIn finally; } } } Code listing in VB.NET Imports System Module MyDecimalDivider Sub Main Try Trigger a divide by zero exception Dim dResult as Decimal = Decimal.Divide5,0 We should never get here Console.WriteLineResult is : {0}, dResult Catch exArithmetic As ArithmeticException Console.WriteLineCaught Arithmetic exception: {0}, _ exArithmetic.Message Catch exDivByZero As DivideByZeroException Console.WriteLineCaught Divide By Zero exception: {0}, _ exDivByZero.Message Catch ex As Exception Console.WriteLineCaught exception: {0}, ex.Message Finally Should always execute Console.WriteLineIn finally End Try End Sub End Module Now save the file and compile the modified MyDecimalDivider.cs MyDecimalDivider.vb in the DOS command line using: Compiling in C csc target:exe MyDecimalDivider.cs Compiling in VB.NET vbc target:exe MyDecimalDivider.vb Run the application MyDecimalDivider.exe and observe the output: Output in C MyDecimalDivider.cs21,9: error CS0160: A previous catch clause already catches all exceptions of this or a super type System.ArithmeticException The error says it all. The ArithmeticException catch handler has been placed above the catch handler that handles exception types of its subclass DivideByZeroException , which effectively hides the catch handler for the DivideByZeroException . Output in VB.NET Caught Arithmetic exception: Attempted to divide by zero. In finally Since ArithmeticException ‘s Catch handler has been placed above the Catch handler for its subclass exception type DivideByZeroException, the Catch handler for the ArithmeticException is asked to handle the error even though the actual exception type that was raised was DivideByZeroException. You’ll observe the same behavior if you place the System.Exception Catch handler above any of the other catch handlers. In order to give DivideByZeroException ’s Catch handler the opportunity to handle the error, place it above the Catch handler that handles ArithmeticException exceptions DivideByZeroException’s super class . To summarize, place Catch handler filters for specific exception types sub classes higher than the handlers for the more generic exception types base classes. Code listing in C Rest of the code omitted for brevity . . . catchDivideByZeroException exDivByZero { Console.WriteLineCaught Divide By Zero exception: {0}, exDivByZero.Message; } catchArithmeticException exArithmetic { Console.WriteLineCaught Arithmetic exception: {0}, exArithmetic.Message; } catchException ex { Console.WriteLineCaught exception: {0}, ex.Message; } Code listing in VB.NET Try Rest of the code omitted for brevity . . . Catch exDivByZero As DivideByZeroException Console.WriteLineCaught Divide By Zero exception: {0}, _ exDivByZero.Message Catch exArithmetic As ArithmeticException Console.WriteLineCaught Arithmetic exception: {0}, exArithmetic.Message Catch ex As Exception Console.WriteLineCaught exception: {0}, ex.Message Finally Should always execute Console.WriteLineIn finally End Try Now let’s try one more thing. We’ll remove the catch handler for the DivideByZeroException , just leaving behind the catch handlers for the System.ArithmeticException and the System.Exception classes. Go ahead and modify the MyDecimalDivider code by commenting out the catch handler for the DivideByZeroException . Compile and run the application. What output do you see this time? Caught Arithmetic exception: Attempted to divide by zero. In finally As shown above, though there was no catch handler for the DivideByZeroException that was raised, the catch handler for ArithemeticException was able to catch the exception since the ArithemeticException class happens to be a base class of the DivideByZeroException class. Similarly, even if we didn’t have the catch handler for the ArithmeticException class, the System.Exception catch handler would have still caught the exception since it’s the parent class for all exception types. So what happens if a DivideByZeroException is raised and you don’t have any of the catch handlers not even the System.Exception catch handler? . You guessed right – the exception would turn into an unhandled exception crashing your application. Try this by removing the try block and all the catch-finally handlers and call Decimal.Divide by passing a value of 0 for the divisor and notice what happens: Output in C Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at System.Decimal.DivideDecimal d1, Decimal d2 at MyDecimalDivider.MainString[] args Output in VB.NET Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at System.Decimal.DivideDecimal d1, Decimal d2 at MyDecimalDivider.Main

7.5 Handling exceptions that are not System.Exception compliant