Supercharge Exception Handling
Get to know the ins and outs of Try-Catch-Finally.
October 30, 2009
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 KillBugs Dead! I briefly covered Try-Catch-Finally blocks. These blocks are.NET's syntax for structured exception handling, a vast improvement overVBScript and Visual Basic On Error syntax. They'll be more familiar to programmerscoming from a C++ or JavaScript background. But either way, there are somesubtle variations on the syntax that you can use to supercharge your exceptionhandling or that might leave you scratching your head about why things aren'tgoing your way. In this article, I'll look a bit more closely at the syntax ofVB .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 previousarticle, ResultHandling.aspx, contains a Try-Catch-Finally block that isprobably a bit more complex than you're likely to put in most of yourprocedures, 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 aredivided.
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 yis " & y.ToString _
& ", x / yis " & 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 ="" _
&"
" & Request.Url.ToString() &"
" _
&"
" & Server.GetLastError().ToString() _ &"
"
Response.Write(sMessage)
Finally
Response.Write("
" _
& "Return to Default.aspx" _
&"
")
End Try
Figure 1. Here ispart of VB .NET's Page Load event procedure. Because one is zero, the codethrows a DivideByZeroException. This exception is defined by the .NETFramework.
The code included in each Catch statement is called anexception filter, consisting of the specific exception object and optional Whenclause. The filter's exception object must be System.Exception or derived fromit. The contents of the When clause must evaluate to True or False and canreference the properties of the Catch block's exception object.
The first three Catch blocks catch a specific type of .NETexception, DivideByZeroException. But they also use the Catch statement'soptional When clause to customize the response further for specific conditionssurrounding the problem. Here, I check whether the divisor "y" is Nothing (inVB .NET), an empty String (which really can't happen with typed variables andOption 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 exceptionthat occurs when the code in the Try block runs is caught by the last Catchblock.
The important concept here is the order of Catch blocks.The rule is to include Catch blocks for more specific exceptions first, followedby increasingly less specific exceptions, generally ending with a Catch blockfor System.Exception. This way you can get as specific as you need whenhandling problems.
C# Exceptions
The basic idea of exceptions and Try-Catch-Finally blocksis the same in C# as it is in VB .NET, but with just enough differences to tripup a programmer moving from one language to the other. Figure 2 shows theequivalent 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 iszero.");
break;
}
}
catch (System.Exception)
{
string sMessage;
sMessage =""
+"
" + Request.Url.ToString() + "
"
+"
" + Server.GetLastError().ToString() +"
";
Response.Write(sMessage);
Server.ClearError();
}
finally
{
Response.Write("
"
+ "Return to Default.aspx"
+"
");
}
Figure 2. Here isthe C# version of the ResultHandling.aspx page.
There are two big differences in this code. The first isthere is no C# equivalent to VB .NET's When clause on the Catch statement, soyou must resort to a switch block or some other construct to achieve the sameresult. The previous code catches the same DivideByZero exception, but thentests 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#, butif you have them in the wrong order in VB .NET, the code happily compiles andexecutes just fine. The C# compiler instead raises a compile-time error if youinclude a more general exception before one that is more specific. It uses theorder of inheritance for the various exceptions to ensure you're not making amistake with it.
Try-Catch-Finally provides a powerful way to handleexceptions in .NET applications. But there is far more than first meets theeye. Learning about its idiosyncrasies in your language of choice will go along way toward robust code and applications.
Don Kiely is senior information architect forInformation Insights, a business and technology consultancy in Fairbanks,Alaska. E-mail him at mailto:[email protected].
About the Author
You May Also Like