.NET Anatomy - Structured Exception Handling in .NET
By Barton Friedland
Published: 7/23/2001
Reader Level: Intermediate
Rated: This article has not yet been rated.
Be the first to rate it!
Tell a Friend
Rate this Article
Printable Version
Discuss in the Forums

Abstract

This article discusses structured exception handling (SEH), a service built into the core of .NET and available to all languages supported by it. Since the infrastructure for this service is built-in, there is very little code required to take full advantage of these features.

As errors and unexpected events are a fact of life, one of the hallmarks of professional programming is the implementation of exception handling code, that is, code that ensures that an error in the execution gets identified and trapped at its source, so that the application can:

  • Continue running
  • Provide helpful information about the source of the error
  • Ensure that the operating system is not brought down

Historically, to write this kind of code meant that the programmer had to do a lot of work, which in turn, meant that it did not get done because of the deadlines that most programmers are up against.

Before .NET, when exception code was implemented, the most common method followed was for a failed function to notify its caller there was a problem by returning a non-standard value. The programmer would then have to write custom code to check for this return value in order to trap the error.

The problem in this scenario, however, was that different functions return different result codes, making it confusing and very time-consuming to tailor the exception handling code for to the function being handled. Also, exceptions returned only failure information and not much else to interpret the cause of the exception.

As technology has developed, different programming languages have presented a variety of different mechanisms for building exception handling code. Of the pre-.NET languages, C++ and Java both supported SEH. The hallmark of SEH is that an error object is employed to carry information about a failure while a handler block in code to deals with that object. However, like most features of any pre-.NET language, the feature only worked within that particular language, and was therefore limited when building a robust and distributed application.

The Promise of .NET

Two of the key promises of .NET are to provide a number of services to the developer that make the development process simpler, while minimizing the amount of code that needs to be written.

The Common Language Runtime (CLR) - that part of .NET that manages the execution of code - is where SEH is implemented. As a result, it is available to any .NET language, and due to .NET's inherent cross-language capabilities, can support this functionality equally as well in a scenario where several languages are used to implement an application.

To use this feature, the programmer simply adds an exception handling block to any operation which may fail. In Visual Basic.NET, the keywords Try and Catch are used to demarcate these exception handling blocks (in C#, try and catch are used - note case sensitivity).

The following diagram shows how the CLR supports SEH when code is being executed by it:

How It Works - Just Like Baseball!

In step one of the diagram above, when the CLR, .NET's managed program execution runtime encounters a Try block, it automatically takes care of step two and writes an exception handler to the call stack - so you don't have to! In step three, the CLR calls the function in the Try block and in step four, when it encounters an exception, it does what in .NET parlance is known as throwing an exception. In step five, the CLR looks back up the stack to find the exception handler that will provide the trace back to the caller. In step six, the CLR tears down the stack and in step 7, passes the trace information, along with control, back to the Catch block of the executing code.

Any code can throw an exception by using the keyword Throw. To do this, simply create a new object of type System.Exception. Try, Catch, and Throw - that's pretty much all that is needed to know in order to work with structured exception handling in .NET.

Except - Finally

There's one more thing - Finally. The result of throwing an exception is that the call stack is torn down. Any expensive resources being used in the code that threw the exception will not be finalized when the stack is torn down. For this purpose, the Visual Basic.NET keyword Finally exists.

Code in a Finally block is executed as the stack is torn down, so finalization code can be placed there. It is therefore very is common to see Try-Catch-Finally blocks in .NET SEH code.

Throw Your Own

Another important design point regarding SEH in .NET is that different types of exceptions can be thrown to indicate different types of application issues.

The .NET Framework provides a base class, System.Exception, from which it is possible to inherit and add additional properties and methods which might better explain the exception to the catcher of the exception. The following diagram shows the hierarchy of this base class as implemented in Beta2 of the .NET Framework:

The System namespace in the .NET Framework defines two classes that inherit from System.Exception:

  • System.ApplicationException: This class is designed for implementing errors occurring within an application. It is thrown by the application, not the CLR.
  • System.SystemException: This is the base class for predefined exceptions in the System namespace. The most severe exceptions-those thrown by the runtime or in non-recoverable conditions-include ExecutionEngineException and StackOverflowException. It is not recommended that you catch SystemExceptions, nor is it good programming practice to throw SystemException in your application. A SystemException is always thrown by the CLR and this class should not be used to create custom exceptions.

These two classes form the basis for most other runtime exceptions. Other exceptions that derive directly from System.Exception include IOException, WebException, and XmlException.

Catching Different Balls

Adding even more power and flexibility to SEH in .NET is the ability to use multiple catch statements in the Try/Catch block in order to handle different exceptions that could be thrown. The order of Catch statements is important. Catch blocks targeted to specific exceptions must be placed before a general exception catch block, or the compiler will issue an error. The runtime determined which Catch block to execute by matching the type of the exception to the name of the exception specified in the Catch block. If there is no specific Catch block, then the exception is caught by a general Catch block, if one exists.

Outside the CLR

One last important point needs to be discussed before going into the code example. It is the fact that .NET can work with code that is outside of the CLR, such as COM components and COM+ services. This is known as interoperability with unmanaged code.

The SEH model implemented in .NET can support exceptions that occur when unmanaged code is involved as well! Interoperation exceptions derive from SystemException and are further extended by ExternalException. Also, Win32Exception, which reports back errors from any calls made to the Win32API and SEHException, which reports back errors from calls made to external code implementing their own SEH, also derive from ExternalException.

Let's Play Ball!

I have provided an application with this code that demonstrates the use of both SystemExceptions and ApplicationExceptions. What follows is a review of the key points.

Application Structure

If the application is opened in Visual Studio.NET and look in the Solution Explorer, the following files will be seen:

The application I have provided is written in two logical projects - one containing an SEH component and the other a client component. This is a standard way for .NET applications to be written, enabling a component to be reused by a variety of clients. I will first look at the SEH component.

SEH Component

The implementation of the SEH component is found in the file Class1.vb under the SEHComponent project tree. The file starts by declaring two distinct ApplicationExceptions that will be used for this application:

'Class Declarations
Dim DBException As New ApplicationException("An application exception as been thrown. This is caused by a failure to connect to the backend database this application depends on.")

Dim SECException As New ApplicationException("An application exception as been thrown. This is caused by security authentication failure.")

The idea here is that there can be many exceptions for many reasons. Good SEH code design process will review the possibilities and document all known exceptions.

The next section shows a function and how an exception is thrown:

Public Function Function1() As String

  'Set exception source properties to identify current exception source
  DBException.Source = "Function1"
  SECException.Source = "Function1"

  Try
    'Code to run would go here
  Throw DBException
    'Code to throw app SECException would go here
  Finally
    MessageBox.Show("Any expensive resources are released here." & _
      "Try block will now terminate.", _
      "Finally Block", MessageBoxButtons.OK, _
      MessageBoxIcon.Information)
  End Try

End Function

Here, properties of the custom exceptions are set and in this function a DBExpection is thrown. Following this, the Finally block would release the resources the function had locked.

The next function, Function2(), does the same thing, but for SECException in order to simulate an SECException.

Function3() does the same thing again, except this function will throw a SystemException as it attempts to perform an illegal mathematical operation. Note in the code block for Function3() that there are stubs for the other exceptions - in real life, all three functions would be one and the conditions for throwing the specific exceptions would be clearly defined.

This code shows that throwing exceptions in .NET is very easy to do - now on to catching…

Client Component

The implementation of the client component uses a Windows Form, but this could just as easily be a Web Form:

First, a form with three button to trigger the three different exceptions is created. Then, the code behind this form triggers the events and catches the exceptions.

Add a Reference

Before the SEHComponent can be used by the client, it is necessary to import a reference to it as follows:

1. Right-click on the References icon in the solution explorer and select Add Reference :

2. A dialogue box will come up - select the "Projects" tab and then select the SEHComponent:

3. Click OK

The reference will now appear as part of the Client Component references.

Catching an Exception

I will look first at the code that handles the first button:

Private Sub btnError1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnError1.Click

  Dim ec As New SEHComponent.Class1()

The first thing it does is to instantiate its own SEHComponent so that it can call SEHComponent methods. The next step is to attempt to do something in a Try block and Catch specific exception types, as follows:

Try
  ec.Function1()

Catch x As ApplicationException
  MessageBox.Show("Message = " + _
    x.Message + " " + "Source = " + _
    x.Source + " " + "Stack Trace = " + _
    x.StackTrace, "Application Error", _
    MessageBoxButtons.OK, _
    MessageBoxIcon.Hand)

Catch x As Exception
    MessageBox.Show("Message = " + _
    x.Message + " " + "Source = " + _
    x.Source + " " + "Stack Trace = " + _
    x.StackTrace, ".NET System Error", _
    MessageBoxButtons.OK, _
    MessageBoxIcon.Stop)

End Try

Note that the code first tries to catch a specific ApplicationException and then a general Exception.

The other two button handlers do exactly the same thing - they just call different functions to simulate different errors.

The Results, Please!

Here is what happens when the DB Exception button is clicked:

The previous dialog is notification that the finally block in the SEHComponent firing and releasing the resources.

This message then follows - the Exception object has passed back all of this information, which can be used any way the programmer sees fit.

Here is what happens when the System Error button is clicked:

The previous dialog is notification that the finally block in the SEHComponent firing and releasing the resources.

And this message is the SystemException being passed back.

Conclusion

SEH in .NET is very straightforward and consistent throughout .NET. This implementation supports all .NET languages, unmanaged code & interoperability and is fully extensible. With features like these, there is no longer any excuse not to implement fully featured SEH in the components and application programmers develop. Doing so will make working with and developing from multiple components manageable.

I would also like to include here for your reference a link to best practices for SEH as included in the .NET SDK.

I hope you have enjoyed this article and learned a lot - now go write some great code!



Marketplace
(Sponsored Links)
What are the green links?
   



 
Copyright © 2007 CMP Tech LLC |
Privacy Policy (4/10/06) | Your California Privacy Rights (4/10/06) | Terms of Service | Advertising Info | About Us | Help