2007-06-07
| Table of Contents: |
| Rate This Article: | Add This Article To: |
( Page 1 of 2 )
Rick Leinecker shows you how to get more information when a C# exception is caught.
I remember those error codes we used to have to handle and interpret in the early days of Windows programming. There are a lot of system error codes, the Winsock errors, for example, are up in the 10,000s.
But with Microsoft Foundation Class (MFC) applications, a new error-handling mechanism known as exceptions was ushered in as the defacto standard for dealing with errors. Exceptions, as a construct, had been around for quite awhile. But they weren't widely used in Windows-based application development until MFC. Of course, Java always had exceptions baked into its infrastructure.
Exceptions make it much easier to deal with error conditions. Exceptions not only deliver the bad news that something went wrong, but they contain a human-readable message so that you don't have to go through a list of thousands of error codes to find out what happened. For more information, check out the article at entitled ASP.NET Exceptions 101 for .NET: What and Why found at http://www.devsource.com/article2/0,1759,1888558,00.asp.
The .NET base class library and the .NET languages add some useful things to the classic exception information. In a tough situation where you're having trouble identifying the underlying problem (has this ever happened to you?), this additional information can really help. In this article I'll talk about ways to use the extra information delivered in an Exception object.
The InnerException Property
All Exception classes have a public property named InnerException. Most of the time, this property will be null. But there are some cases where it's not null and it contains additional information that will help you find the underlying problem. This is almost always the case when the error that your code caught was thrown from within a catch block that caught another exception. Let's use a simple example to illustrate this.
Here are three methods that we'll use for the example. None of them handle exceptions, so the exception handling responsibility calls on the calling code.
FileStream m_objReader = null;
void Open( string strFilePath )
{
m_objReader = File.OpenRead(strFilePath);
}
void Read()
{
byte[] FileData = new byte[m_objReader.Length];
m_objReader.Read(FileData, 0, FileData.Length);
}
void Close()
{
m_objReader.Close();
}
I'll use a method to wrap these three method calls as follows:
void DoFileIO()
{
try
{
Open(@"c:\MissingFile.dat");
Read();
Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
Since there is no file named c:\MissingFile.dat, an exception is thrown and the MessageBox displays an error message. For a simple program that error/exception handling is adequate. But in more complex programs, you might want to pass the exception on up the line and let some other code handle it. If this is the case, you have several options. Option one is to not catch the exception in the DoFileIO method—this will automatically pass control to code up the line that is ready to catch the exception. Option two is to catch the exception from within the DoFileIO method, perform some necessary operations, and just rethrow it. But the last option is what we're interested in. We can throw a new exception with a custom message that we want to pass up the line, and include the caught exception, too. The caught exception becomes an inner exception to the new exception that we throw. Now, the code up the line can see the original exception and the new exception. Complete information for both exceptions is available. The following code shows how to throw a new exception and include the caught exception:
throw new Exception("My Message Here", ex);
The new DoFileIO method will be as follows:
void DoFileIO()
{
try
{
Open(@"c:\MissingFile.dat");
Read();
Close();
}
catch (Exception ex)
{
throw new Exception("Houston, we have a problem", ex);
}
}
Now we have to call the DoFileIO method from within a try/catch block and deal with the exception. In the catch block we simply look at the caught exception's InnerException property. If it is not null, we can examine the information contained within it. The following code catches the exception, and shows the InnerException message if it exists.
try
{
DoFileIO();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
if (ex.InnerException != null)
{
MessageBox.Show(ex.InnerException.Message.ToString());
}
}
What happens if the inner exception has an inner exception? Then you need more than a simple if statement. As a matter of fact, there is no limit to the number of inner exceptions you can experience. What you need to do is set up a while loop that moves through the chain of inner exceptions as long as they exist as follows:
try
{
DoFileIO();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
Exception Inner = ex.InnerException;
while( Inner != null )
{
MessageBox.Show(Inner.Message.ToString());
Inner = Inner.InnerException;
}
}
Using inner exceptions has helped me work through some of my gnarliest issues. I don't use it as a general rule, but when I need it I'm glad the mechanism is there.
![]() |
|


