Supercharge Exception Handling

Get to know the ins and outs of Try-Catch-Finally.

Troubleshooting Tips and Tricks

LANGUAGES: C# | VB.NET

TECHNOLOGIES: Exception Handling

 

Supercharge Exception Handling

Get to know the ins and outs of Try-Catch-Finally.

 

By Don Kiely

 

In my article Kill Bugs Dead! I briefly covered Try-Catch-Finally blocks. These blocks are .NET's syntax for structured exception handling, a vast improvement over VBScript and Visual Basic On Error syntax. They'll be more familiar to programmers coming from a C++ or JavaScript background. But either way, there are some subtle variations on the syntax that you can use to supercharge your exception handling or that might leave you scratching your head about why things aren't going your way. In this article, I'll look a bit more closely at the syntax of VB .NET and C# so you have a better chance of boosting your exception handling.

VB .NET Exceptions

One of the Web pages in the sample code from my previous article, ResultHandling.aspx, contains a Try-Catch-Finally block that is probably a bit more complex than you're likely to put in most of your procedures, but it'll do for explanation. Figure 1 contains a portion of VB .NET's version of the Page Load event procedure, in which a few numbers are divided.

 

Dim x As Integer = 44

Dim y As Integer = 0

Dim z As Double

Dim zi As Double

 

Try

   z = x / y

   zi = x \ y

 

   lblResult.Text = "When x is " & x.ToString _

      & " and y is " & y.ToString _

      & ", x / y is " & z.ToString _

      & ", and x \ y is " & zi.ToString & "."

 

Catch ex As DivideByZeroException When y.ToString = Nothing

   Response.Write("The divisor is nothing.")

 

Catch ex As DivideByZeroException When y.ToString = ""

   Response.Write("The divisor is an empty string.")

 

Catch ex As DivideByZeroException When y = 0

   Response.Write("The divisor is zero.")

 

Catch ex As Exception

   Dim sMessage As String

   sMessage = "<font face='Comic Sans MS'>" _

          & "<h4>" & Request.Url.ToString() & "</h4>" _

          & "<pre>" & Server.GetLastError().ToString() _

          & "</pre></h3>"

   Response.Write(sMessage)

 

Finally

   Response.Write("<P><FONT face='Comic Sans MS'>" _

      & "<A href='Default.aspx'>Return to Default.aspx" _

      & "</A></FONT></P>")

End Try

Figure 1. Here is part of VB .NET's Page Load event procedure. Because one is zero, the code throws a DivideByZeroException. This exception is defined by the .NET Framework.

 

The code included in each Catch statement is called an exception filter, consisting of the specific exception object and optional When clause. The filter's exception object must be System.Exception or derived from it. The contents of the When clause must evaluate to True or False and can reference the properties of the Catch block's exception object.

 

The first three Catch blocks catch a specific type of .NET exception, DivideByZeroException. But they also use the Catch statement's optional When clause to customize the response further for specific conditions surrounding the problem. Here, I check whether the divisor "y" is Nothing (in VB .NET), an empty String (which really can't happen with typed variables and Option Strict On), or equal to zero.

 

The last Catch block is a catch-all block of last resort. Because all exceptions are derived from System.Exception, any other exception that occurs when the code in the Try block runs is caught by the last Catch block.

 

The important concept here is the order of Catch blocks. The rule is to include Catch blocks for more specific exceptions first, followed by increasingly less specific exceptions, generally ending with a Catch block for System.Exception. This way you can get as specific as you need when handling problems.

 

C# Exceptions

The basic idea of exceptions and Try-Catch-Finally blocks is the same in C# as it is in VB .NET, but with just enough differences to trip up a programmer moving from one language to the other. Figure 2 shows the equivalent code from the C# version of the ResultHandling.aspx page.

 

int x = 44;

int y = 0;

double z;

double zi;

 

try

{

   z = (double)x / (double)y;

   zi = x / y;

   lblResult.Text = "When x is " + x.ToString()

      + " and y is " + y.ToString()

      + ", x / y is " + z.ToString()

      + ", and x \\ y (integral) is " + zi.ToString()

      + ".";

}

catch (DivideByZeroException ex)

{

   switch (y.ToString())

   {

      case null:

         Response.Write("The divisor is nothing.");

         break;

      case "":

         Response.Write("The divisor is an empty string.");

         break;

      case "0":

          Response.Write("The divisor is zero.");

         break;

   }

}

catch (System.Exception)

{

   string sMessage;

   sMessage = "<font face='Comic Sans MS'>"

      + "<h4>" + Request.Url.ToString() + "</h4>"

      + "<pre>" + Server.GetLastError().ToString()

      + "</pre></h3>";

 

   Response.Write(sMessage);

   Server.ClearError();

}

finally

{

   Response.Write("<P><FONT face='Comic Sans MS'>"

      + "<A href='Default.aspx'>Return to Default.aspx"

      + "</A></FONT></P>");

}

Figure 2. Here is the C# version of the ResultHandling.aspx page.

 

There are two big differences in this code. The first is there is no C# equivalent to VB .NET's When clause on the Catch statement, so you must resort to a switch block or some other construct to achieve the same result. The previous code catches the same DivideByZero exception, but then tests the value of variable y to see whether it is null, an empty string, or 0.

 

The order of the catch blocks also is important in C#, but if you have them in the wrong order in VB .NET, the code happily compiles and executes just fine. The C# compiler instead raises a compile-time error if you include a more general exception before one that is more specific. It uses the order of inheritance for the various exceptions to ensure you're not making a mistake with it.

 

Try-Catch-Finally provides a powerful way to handle exceptions in .NET applications. But there is far more than first meets the eye. Learning about its idiosyncrasies in your language of choice will go a long way toward robust code and applications.

 

Don Kiely is senior information architect for Information Insights, a business and technology consultancy in Fairbanks, Alaska. E-mail him at mailto:[email protected].

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish