Catching the base class of an exception - C#

All exception in C# inherit from the Exception base class.

This is either directly, as is the case for an ApplicationException:

public class ApplicationException : Exception

Or indirectly, as is the case for ArgumentException:

public class ArgumentException : SystemException
public class SystemException : Exception

You may then find that, when executing code that could throw multiple types of exceptions, you want to handle all the exceptions with the same base type in the same way.

Catching a base exception

Let's take a look at the following example:

using System;

class CatchingBaseExceptions 
{
    public static void Main (string[] args) 
    {
        try
        {
            PrintName("");
        }
        catch(SystemException e) 
        {
            Console.WriteLine($"Caught as: {e.GetType()}");
        }
    }

    static void PrintName(string name)
    {
        if(name == null)
        {
            throw new NullReferenceException("Name is null");
        }

        if(name.Length == 0)
        {
            throw new ArgumentException("Name should not be empty");
        }

        Console.WriteLine($"Hello {name}!");
    }
}

Here we have two exceptions that could be thrown: NullReferenceException and ArgumentException.

Both of these inherit from SystemException, so if we pass null into the PrintName method, we would see it caught:

Caught as: NullReferenceException

As well as passing in an empty string:

Caught as: ArgumentException

Note that although we are catching the base class, the exception that is passed into the catch block is still the same type that was thrown.

Order is important!

What if we wanted to catch NullReferenceException separately?

Let's try adding another catch to the previous example, so we can handle when null is passed in:

public static void Main (string[] args) 
{
    try
    {
        PrintName("");
    }
    catch(SystemException e) 
    {
        Console.WriteLine($"Caught as: {e.GetType()}");
    }
    catch(NullReferenceException e)    {        // Caught the NullReferenceException that was thrown        Console.WriteLine($"{e.GetType()} - The name was null.");    }}

Instead of the code executing correctly, we get this error back from the compiler:

error CS0160: A previous catch clause already catches all exceptions of this or a super type `System.SystemException'

The order in which we add the catch statements is important. If an exception is caught in a try block, it will check each catch block in the order they were written.

And since NullReferenceException is of type SystemException, the second catch block will never be used.