In this article, we are going to learn about different ways to catch multiple exceptions in C#. Utilizing try-catch block is the best way to manage exceptions. It also enables developers to manage exceptions however they want. Using a single catch block is one of the models which we can use to control exceptions.

To download the source code for this article, you can visit our GitHub repository.

Lets’s start.

Catching Multiple Exceptions Separately

If we want to handle the exceptions separately and make a particular decision for each one, we should have specific information about the exceptions that may occur. In this case, the best way is to use an individual catch block for each exception. 

To be precise, let’s suppose we want to take two numbers from the user and then divide the first one by the other. Due to the string format of the input values, we should convert them to a numerical form. But if something goes wrong, we want to show the end-user a reason for the failed operation.

Let’s create the MultipleCatches method to do that:

public static int MultipleCatches(string numeratorParam, string denominatorParam)
{
    try
    {
        var numerator = Convert.ToUInt32(numeratorParam);
        var denominator = Convert.ToUInt32(denominatorParam);

        return (int)(numerator / denominator);
    }
    catch (FormatException)
    {
        Console.WriteLine("Format Exception!");
    }
    catch (DivideByZeroException)
    {
        Console.WriteLine("Divide By Zero Exception!");
    }
    catch (OverflowException)
    {
        Console.WriteLine("Overflow Exception!");
    }

    return -1;
}

While converting parameters to an unsigned integer type with the Convert.ToUInt32 method, our application may throw two exceptions FormatException or OverflowException. The division line also may throw a DivideByZeroException. So, we’ve handled all the potential exceptions that can happen in this case.

Catching Multiple Exceptions in a Single Catch Block

Sometimes, we need to do the same work for all the exceptions. To do that, we use the single-catch-block model and group the type of exceptions we want to handle.

Let’s create a SingleCatchWithWhen method to explore this model:

public static int SingleCatchWithWhen(string numeratorParam, string denominatorParam)
{
    try
    {
        var numerator = Convert.ToUInt32(numeratorParam);
        var denominator = Convert.ToUInt32(denominatorParam);

        return (int)(numerator / denominator);
    }
    catch (Exception ex) when (ex is FormatException ||
                               ex is DivideByZeroException ||
                               ex is OverflowException)
    {
        return -1;
    }
}

In this method, we pack all the potential exceptions at one catch block using the when keyword. It is a shorter way to declare exceptions to the catch block.

Separating Exceptions in a Single Catch Block

To show the way to separate exceptions in a single catch block, let’s create the SingleCatchSwitchCase method:

public static int SingleCatchSwitchCase(string numeratorParam, string denominatorParam)
{
    try
    {
        var numerator = Convert.ToUInt32(numeratorParam);
        var denominator = Convert.ToUInt32(denominatorParam);

        return (int)(numerator / denominator);
    }
    catch (Exception ex)
    {
        switch (ex)
        {
            case FormatException:
                Console.WriteLine("Format Exception!");
                break;
            case DivideByZeroException:
                Console.WriteLine("Divide By Zero Exception!");
                break;
            case OverflowException:
                Console.WriteLine("Overflow Exception!");
                break;
        }
    }

    return -1;
}

We catch all the exceptions in a single catch block and separate them using a switch-case pattern. Fortunately, switch (ex) can recognize the type of the ex variable and compare it with each case. On the other hand, we can also use the if-else pattern instead of a switch-case model.

To separately manage all exceptions in one catch block, we can utilize the switch pattern syntax too.

So, let’s create the SingleCatchSwitchPattern method to explain it:

public static int SingleCatchSwitchPattern(string numeratorParam, string denominatorParam)
{
    try
    {
        var numerator = Convert.ToUInt32(numeratorParam);
        var denominator = Convert.ToUInt32(denominatorParam);

        return (int)(numerator / denominator);
    }
    catch (Exception ex)
    {
        string str = ex switch
        {
            FormatException => "Format Exception!",
            DivideByZeroException => "Divide By Zero Exception!",
            OverflowException => "Overflow Exception!",
            _ => "Unknown Exception!"
        };

        Console.WriteLine(str);
    }

    return -1;
}

In our method, the lambda expressions and _ case match and filter all values. We use this model to generate an appropriate message for each exception. In the str variable, we keep the selected string to print on the console.

Multiple Catch Blocks vs Single Catch Blocks

Once the application throws the exception the question is, do multiple catch blocks have better performance or a single catch block? In fact, after throwing an exception, the try-catch should have a switching pattern for delivering the exception to the first best case. When we use multiple catch blocks, the compiler defines the switching model automatically. But if we write a single catch block, we should specify that switching pattern manually.

Wanna join Code Maze Team, help us produce more awesome .NET/C# content and get paid? >> JOIN US! <<

At this time, both patterns may have the same performance if the developer utilizes a fast decision-maker model in the catch block. What does it mean? It means, when the developer uses a slow flow controller like an if-else model to manage exceptions, they cannot expect to achieve the same performance as the multiple catch blocks. But fast flow controllers such as switch-case and switch-when models can be as fast as multiple catch blocks.

Conclusion

So, in this article, we’ve learned how to catch multiple exceptions using different approaches.  We’ve seen that we can use the when keyword to achieve that and also combine it with the switch-case expression.