C Sharp

Constructing an Exception Object

As of this writing, there are four different constructors for the System.Exception class: -

public Exception ();
public Exception(String);
protected Exception(SerializationInfo, StreamingContext);
public Exception(String, Exception);

The first constructor listed above is the default constructor. It takes no arguments and simply defaults all member variables. This exception is typically thrown as follows: -

// Error condition reached.
throw new Exception();

The second exception constructor takes as its only argument a String value that identifies an error message and is the form that you've seen in most of the examples in this chapter. This message is retrieved by the code catching the exception via the System.Exception.Message property. Here's a simple example of both sides of this exception propagation: -

using System;
class ThrowException3
{
    class FileOps
    {
        public void FileOpen(String fileName)
        {
            // ...
            throw new Exception("Oh bother");
        }
        public void FileRead()
        {
        }
    }
    public static void Main()
    {
        // Code catching exception.
        try
        {
            FileOps fileOps = new FileOps();
            fileOps.FileOpen("c:\\test.txt");
            fileOps.FileRead();
        }
        catch(System.Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

The third constructor initializes an instance of the Exception class with serialized data.

Finally, the last constructor enables you to specify not only an error message but also what's known as an inner exception. The reason for this is that when handling exceptions, at times you'll want to massage the exception a bit at onelevel of the call stack before passing it further up the call stack. Let's look at an example of how you might use this feature.

Let's say that in order to ease the burden on your class's client, you decide to throw only one type of exception. That way the client only has to catch one exception and reference the exception's InnerException property. This has the added benefit that if you decide to modify a given method to throw a new type of exception after the client code has been written, the client doesn't have to be updated unless it wants to do something specific with this exception.

In the following example, notice that the client code catches the top-level System.Exception and prints a message contained in that exception's inner exception object. If at later date the DoWork method throws other kinds of exceptions--as long as it does so as inner exceptions of an System.Exception object-the client code will continue to work.

using System;
using System.Globalization;
class FooLib
{
    protected bool IsValidParam(string value)
    {
        bool success = false;
        if (value.Length == 3)
        {
            char c1 = value[0];
            if (Char.IsNumber(c1))
            {
                char c2 = value[2];
                if (Char.IsNumber(c2))
                {
                    if (value[1] == '.')
                        success = true;
                }
            }
        }
        return success;
    }
    public void DoWork(string value)
    {
        if (!IsValidParam(value))throw new Exception
                ("", new FormatException("Invalid parameter specified"));
        Console.WriteLine("Work done with '{0}'", value);
    }
}
class FooLibClientApp
{
    public static void Main(string[] args)
    {
        FooLib lib = new FooLib();
        try
        {
            lib.DoWork(args[0]);
        }
        catch(Exception e)
        {
            Exception inner = e.InnerException;
            Console.WriteLine(inner.Message);
        }
    }
}