Exceptions in C# - InnerException
(Page 3 of 4 )
One of the important properties of the Exception class is InnerException. As the term implies, it is an exception within an exception. Here is an example that illustrates its usage:
class Program
{
static void Main( string [] args)
{
int [] a = new int [3];
try
{
PopulateArray(a);
}
catch ( Exception e)
{
//printing the exception details
WriteExceptionDetails(e);
}
}
static void PopulateArray( int [] a)
{
try
{
a[0] = 10; //ok
a[1] = 20; //ok
a[2] = 30; //ok
a[3] = 40; //No such element at position 3.
}
catch ( Exception e)
{
Exception e2 = new Exception ( "Array access exception" , e);
throw e2;
}
}
static void WriteExceptionDetails( Exception e)
{
Console .WriteLine( "Message: {0}" , e.Message);
Console .WriteLine( "Source: {0}" , e.Source);
Console .WriteLine( "InnerException: {0}" , e.InnerException);
Console .WriteLine( "StackTrace: {0}" , e.StackTrace);
Console .WriteLine( "TargetSite: {0}" , e.TargetSite);
}
}
Notice the code in the PopulateArray() method:
Exception e2 = new Exception ( "Array access exception" , e);
throw e2;
The Exception constructor is overloaded to accept a message and another exception (the inner exception). We take advantage of this constructor by recording the exception that happened in PopulateArray(). Then, we can throw e2 (with its inner exception) to be caught by the calling method ( Main() ). After Main() catches the exception in its catch block, it writes the exception details to the screen (including the inner exception from PopulateArray()) by calling WriteExceptionDetails().
Since there are many types of exceptions that can be thrown, it comes as no surprise that we can have many catch blocks. Every catch block handles the type of exception that we expect to be thrown. Ponder the following code:
class Program
{
static void Main( string [] args)
{
int [] a = new int [3];
try
{
a[0] = 10; //ok
a[1] = 20; //ok
a[2] = 30; //ok
a[3] = 40; //No such element.
}
catch ( IndexOutOfRangeException e)
{
Console .WriteLine( "An index out of range exception has
occurred!" );
}
catch ( ArgumentException e)
{
Console .WriteLine( "An argument exception has occurred!" );
}
catch ( ArrayTypeMismatchException e)
{
Console .WriteLine( "An array type mismatch exception has
occurred!" );
}
catch ( Exception e)
{
//printing the exception details
WriteExceptionDetails(e);
}
}
static void WriteExceptionDetails( Exception e)
{
Console .WriteLine( "Message: {0}" , e.Message);
Console .WriteLine( "Source: {0}" , e.Source);
Console .WriteLine( "InnerException: {0}" , e.InnerException);
Console .WriteLine( "StackTrace: {0}" , e.StackTrace);
Console .WriteLine( "TargetSite: {0}" , e.TargetSite);
}
}
IndexOutOfRangeException is the best match for the type of exception that occurred in this code. Therefore, the output of the program will be: "An index out of range exception has occurred." The order of the catch blocks matters; we catch exceptions from the most specific to the most general. As a matter of fact, the compiler will issue an error message if you try to catch a more general exception before a specific exception (try to move catch (Exception e) and place it before catch (IndexOutOfRangeException e) and see what happens).
Next: The Finally Block >>
More C# Articles
More By Ayad Boudiab