BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

C# Programming
.NET 1.1+

Re-throwing Exceptions and the Call Stack

When an exception is caught, it may need to be re-thrown to be handled by methods that appear deeper in the call stack. The way in which an exception object is re-thrown can lead to changes in the information that it holds.

Throwing Exceptions

A common process when handling exceptions is to catch them, perform some processing and re-throw the exception to be handled again by calling methods. The processing performed can vary widely depending upon the circumstances. In simple cases, you may wish to extract information from an Exception object's properties and log those details to a file or event log. In other cases, you may wish to construct a new exception that contains further information, or modify the existing exception, before throwing the object to be handled again.

throw;

There are two ways in which you can re-throw an exception. The first is to use the throw keyword with no parameter within a catch block. Using this approach maintains all of the information within the exception, including the StackTrace and TargetSite properties. StackTrace is important because it shows all of the calls that were made between the current method and the place where the exception was thrown. The TargetSite property holds the name of the member that originally threw the exception.

We can demonstrate this by creating a console application containing the following code. The Main method calls RethrowingMethod, which calls OriginalFailure. The OriginalFailure method throws a new exception, which is captured and then re-thrown by RethrowingMethod. The Main method outputs the details of the target site and stack trace from the exception.

static void Main()
{
    try
    {
        RethrowingMethod();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.TargetSite);
        Console.WriteLine(ex.StackTrace);
    }
}

private static void RethrowingMethod()
{
    try
    {
        OriginalFailure();
    }
    catch (Exception ex)
    {
        throw;
    }
}

private static void OriginalFailure()
{
    throw new Exception("It's broken!");
}

As we are using "throw" alone, the outputted stack trace and target site are based upon the original exception's location. Both show "OriginalFailure" as the starting point for the exception:

Void OriginalFailure()
   at ThrowTest.Program.OriginalFailure() in d:\ThrowTest\Program.cs:line 41
   at ThrowTest.Program.RethrowingMethod() in d:\ThrowTest\Program.cs:line 35
   at ThrowTest.Program.Main() in d:\ThrowTest\Program.cs:line 18

throw ex;

If you create a new exception based upon one you have caught, you can throw the replacement by specifying it after the throw command. Usually you should not use this approach to re-throw an exception because the StackTrace and TargetSite properties are reset. This means that exception will appear to originate from the method that re-throws it.

To demonstrate the difference, replace the "throw;" line in RethrowingMethod with the following:

throw ex;

Run the program again to see the results. You should find that there is no mention of the OriginalFailure method in either the target site or the stack trace.

Void RethrowingMethod()
   at ThrowTest.Program.RethrowingMethod() in d:\ThrowTest\Program.cs:line 35
   at ThrowTest.Program.Main() in d:\ThrowTest\Program.cs:line 18
1 November 2015