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+

Throwing Exceptions in C#

The thirty-fifth part of the C# Fundamentals tutorial completes an investigation of exception handling. In this article we will consider the throwing of exceptions to report error conditions. This includes the use of standard and custom exception types.

Why Throw Exceptions?

In the previous part of the C# Fundamentals tutorial, I introduced exception handling and the facility to catch exceptions using the try / catch / finally block in C#.

During normal processing, it is possible for an error condition to be detected. In older languages you might exit the failing subroutine early and provide a return code to indicate the status. This is possible with C# but does not take advantage of the exception handling features provided by the language. It is preferable to raise or throw exceptions explicitly when error conditions occur and allow exceptions to be captured by a try / catch / finally block or by the C# runtime system.

You should throw exceptions only when an unexpected or invalid activity occurs that prevents a method from completing its normal function; exception handling should not be used for normal program flow instead of conditional processing. It can be difficult to maintain code that misuses exception handling.

Good uses of exceptions include:

  • throwing an exception when an invalid parameter value is passed to a method. The ArgumentException or one of its derived exception classes should be thrown in this situation.
  • throwing an exception when a call is made to a method that cannot operate because other steps must be taken beforehand. An InvalidOperationException could be thrown in this case.

Throwing an Exception

To raise an exception you use the throw command. The syntax is as follows:

throw exception;

The exception is an exception object containing the details of the error being raised. This can be declared as an object and initialised before the throw command or included in the throw statement, using the new keyword and one of the exception's constructors to set the object's properties.

The following example uses a console application that requires at least one start-up parameter in order to operate. If no start-up parameter is provided, an ArgumentException is thrown. The constructor has a single string parameter containing the error message.

using System;

namespace BlackWasp
{
    class TestApp
    {
        static void Main(string[] args)
        {
            // Check that a parameter was provided
            if (args.Length == 0)
            {
                throw new ArgumentException("A start-up parameter is required.");
            }

            Console.WriteLine("{0} argument(s) provided", args.Length);
        }
    }
}

When started with a parameter, the program runs without error and outputs the number of parameters provided. If no arguments are specified the body of the if statement throws an exception. This avoids unexpected exceptions occurring later due to the parameters being invalid.

NB: The class of exception object to throw should be appropriate for the error condition. Each exception object has constructors that may differ from that shown above. For details of other standard exception classes visit the MSDN web site.

Re-Throwing Exceptions

When you trap an exception in a catch block, the exception is considered to have been processed and code execution continues normally. Sometimes you will want to catch the exception but still have it thrown to be caught again. For example, you may catch and log exceptions and then re-throw them to be handled by the calling function.

When an exception is thrown explicitly using the previous syntax, a new exception object is created. This contains only the basic information that you specify; information such as the stack trace of the original exception is lost. To re-throw the original exception and retain all additional information, use the throw command without specifying an exception object:

throw;

The following sample demonstrates how this syntax is used. For simplicity, the methods called are not defined so this code cannot be directly executed.

static void Main(string[] args)
{
    try
    {
        InitialiseData(args[0]);
        SaveToDisk();
    }
    catch (Exception ex)
    {
        // Log the details of any exception and re-throw
        LogException();
        throw;        
    }
}

Using the InnerException Property

In the previous article in the tutorial, I described the InnerException property, which can be used to hold the details of an initial exception that caused a further exception to be thrown. This mechanism is useful when you wish to throw one exception in response to another without losing the original problem's details.

The following example extends the re-throw sample above by throwing a FileNotFoundException with a new error message and the caught exception's details in the InnerException property.

static void Main(string[] args)
{
    try
    {
        InitialiseData(args[0]);
        SaveToDisk();
    }
    catch (Exception ex)
    {
        // Log the details of any exception and re-throw
        LogException();
        throw new System.IO.FileNotFoundException("Invalid file argument", ex);
    }
}

NB: The above code is provided as an example of setting the InnerException property. It is not good practice to use a catch-all and throw a new exception as this can mask serious problems.

9 April 2007