How to Catch Multiple Exceptions in C#: A Complete Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Catch them all: how to catch multiple exceptions in C# without code duplication

\n\n

Imagine: you are writing an application that works with files, networks, and databases. In one method, FileNotFoundException, IOException, or UnauthorizedAccessException could be thrown. The classic approach is three catch blocks with identical code inside. This violates the DRY (Don't Repeat Yourself) principle and turns the code into "spaghetti".

\n\n

The good news: C# has several elegant ways to catch multiple exceptions at once. In this tutorial, we will cover all the options — from basic to advanced — and you will learn how to write clean, maintainable error handling code.

\n\n

Why is this important? A real-world scenario

\n\n

Suppose you are developing a console application for backup. It reads files, compresses them, and sends them to a remote server. Different exceptions can occur at each stage:

\n\n
    \n
  • Reading a file: FileNotFoundException, PathTooLongException
  • \n
  • Compression: OutOfMemoryException
  • \n
  • Sending: HttpRequestException, TimeoutException
  • \n
\n\n

If you write a separate catch for each exception with the same logging, the code becomes bulky. And if you later need to change the logic, you will have to edit it in three places. This is exactly where the ability to catch multiple exceptions at once comes in handy.

\n\n

Method 1. Classic: multiple catch blocks (before C# 6)

\n\n

The simplest and most obvious method is to write several catch blocks in a row. C# itself will select the appropriate block based on the exception type:

\n\n
try\n{\n    // Code that may throw different exceptions\n    string content = File.ReadAllText(@"C:\\data\\config.txt");\n    int value = int.Parse(content);\n    await SendToServerAsync(value);\n}\ncatch (FileNotFoundException ex)\n{\n    Console.WriteLine($"File not found: {ex.Message}");\n    LogError(ex);\n}\ncatch (FormatException ex)\n{\n    Console.WriteLine($"Invalid data format: {ex.Message}");\n    LogError(ex);\n}\ncatch (HttpRequestException ex)\n{\n    Console.WriteLine($"Network error: {ex.Message}");\n    LogError(ex);\n}
\n\n

Pros: transparent, easy to read, you can handle each exception differently.
\nCons: if the actions are the same — code duplication.

\n\n

Method 2. Catching multiple exceptions in one catch (C# 6+)

\n\n

Starting with C# 6, you can list multiple exception types separated by | in a single catch block. This reduces duplication and maintains readability:

\n\n
try\n{\n    // Risky code\n}\ncatch (FileNotFoundException | FormatException | HttpRequestException ex)\n{\n    Console.WriteLine($"An error occurred: {ex.Message}");\n    LogError(ex);\n    // Additional logic common to all three types\n}
\n\n

Important: all exceptions must be compatible in hierarchy. You cannot mix, for example, IOException and NullReferenceException — they are not related by a common ancestor other than Exception. But in C# 6+, this is allowed; the compiler simply casts the variable ex to the common base type.

\n\n

When to use this method?

\n
    \n
  • When the handling logic is identical for all exceptions.
  • \n
  • When you want to avoid nested if or switch blocks.
  • \n
  • In small methods where brevity is important.
  • \n
\n\n

Method 3. Exception filters (C# 6+)

\n\n

Exception filters are a powerful mechanism that allows you to catch exceptions based on a condition using the when keyword. You can catch the same exception but with different logic depending on its properties:

\n\n
try\n{                

Blogs

Book Recommendations