# C# Exception Handling

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Exception = an unexpected event that occurred during program execution that disrupts the desired flow of the program.</div>
</div>

As mentioned above, exceptions disrupt the flow of the program and terminate the program abnormally. It's the developer's responsibility to handle exceptions gracefully. If these errors are not handled properly, the program might crash and you may never know the root cause of failure.

Handling or responding to exceptions is called Exception Handling.

In C#, exception handling is achieved using 4 keywords :

* **try**: code that might generate exceptions is put inside the `try` block.
    
* **catch:** This block `'catches'` the exception generated inside `try` block. The developer could decide what's need done once an exception is generated i.e. logging the stack trace, logging error messages, showing error prompts to the user etc.
    
* **finally:** This code block when written will always execute no matter whether an exception is raised or not. This is useful in scenarios where some clean-up code is required for example closing a file.
    
* **throw:** `throw` keyword is used to generate new exceptions in code.
    

> In C#, exceptions are a type represented by classes derived from class [Exception](https://learn.microsoft.com/en-us/dotnet/api/system.exception?view=net-7.0).

## Exception classes

C# .NET includes built-in exception classes for every possible error. The [Exception](https://learn.microsoft.com/en-us/dotnet/api/system.exception?view=net-7.0) class is the base class of all the exception classes.

below is a list of common C# exception classes :

* `System.NullReferenceException` – Very common exception related to calling a method on a null object reference.
    
* `System.IndexOutOfRangeException` – Occurs attempting to access an array element that does not exist.
    
* `System.IO.IOException` – Used around many file I/O type operations.
    
* `System.NET.WebException` – Commonly thrown around any errors performing HTTP calls.
    
* `System.Data.SqlClient.SqlException` – Various types of SQL Server exceptions.
    
* `System.StackOverflowException` – If a method calls itself recursively, you may get this exception.
    
* `System.OutOfMemoryException` – If your app runs out of memory.
    
* `System.InvalidCastException` – If you try to cast an object to a type that it can’t be cast to.
    
* `System.InvalidOperationException` – Common generic exception in a lot of libraries.
    
* `System.ObjectDisposedException` – Trying to use an object that has already been disposed of.
    

## Handling exception

```csharp
try {
    int num = 0;
    // code that may raise an exception 
    int divideByZero = 7 / num;
}
catch (Exception e){
    // 'catching' and 'handling' the exception
    Console.WriteLine("Exception has occurred :" + e.Message);
}
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This is a simple example to illustrate exception handling. We could deal with this particular scenario better in practice by checking explicitly for the divisor being zero before operating. <strong>Checking for preventable errors is preferable</strong> to relying on try/catch blocks because exceptions are relatively expensive to handle, taking hundreds of clock cycles or more</div>
</div>

running the above program shows the below output

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1687333345771/71ca3259-a3c9-4523-a307-a44ddb867138.png align="center")

if finally block is also available then it also gets executed

```csharp
try {
    int num = 0;
    // code that may raise an exception 
    int divideByZero = 7 / num;
}
catch (Exception e){
    // 'catching' and 'handling' the exception
    Console.WriteLine("Exception has occurred :" + e.Message);
}
finally {
    Console.WriteLine("Inside finally");
}
```

### How exception handling workflow works

When an exception is thrown within a try statement, the CLR performs a test:

*Does the try statement have any compatible catch blocks?*

• If so, execution jumps to the compatible catch block, followed by the finally block (if present), and then execution continues normally.

• If not, execution jumps directly to the finally block (if present), then the CLR looks up the call stack for other try blocks; if found, it repeats the test.

If no function in the call stack takes responsibility for the exception, the program terminates.

## Multiple Catch Blocks 

A program code that is written inside a `try` block might raise multiple types of exceptions. These multiple types of exceptions could be handled using multiple catch blocks. Remember that a more specialized catch block should come before a generalized one. Otherwise, the compiler will show a compilation error.

```csharp
    class Test {
        static void Main(string[] args) {
            try {
                byte b = byte.Parse(args[0]);
                Console.WriteLine(b);
            }
            catch (IndexOutOfRangeException) {
                Console.WriteLine("Please provide at least one argument");
            }
            catch (FormatException) {
                Console.WriteLine("That's not a number!");
            }
            catch (OverflowException) {
                Console.WriteLine("You've given me more than a byte!");
            }
        }
    }
```

## Catching all exception types

a `catch` block without bracket or having type as `Exception` can handle all exception types.

```csharp
        try{
            div = 100 / x;
            Console.WriteLine("Not executed line");
        }
        catch {
            Console.WriteLine("oException");
        }
```

## Throwing an Exception

using `throw` keyword, an exception could be thrown programmatically.

```csharp
public class ProgramLog {
    FileStream logFile = null!;
    public void OpenLog(FileInfo fileName, FileMode mode) { }
    public void WriteLog() {
        if (!logFile.CanWrite) {
            throw new InvalidOperationException("Logfile cannot be read-only");
        }
        // Else write data to the log and return.
    }
}
```

# **User-defined exceptions**

a user-defined exception class can be created by deriving from the `Exception` class.

When creating your own exceptions, end the class name of the user-defined exception with the word "Exception", and implement the three common constructors, shown below code :

```csharp
using System;
public class EmployeeListNotFoundException : Exception {
    public EmployeeListNotFoundException() {
    }
    public EmployeeListNotFoundException(string message)
        : base(message) {
    }
    public EmployeeListNotFoundException(string message, Exception inner)
        : base(message, inner) {
    }
}
```

That's it for this article, please share your feedback in the comments.

### References and further reading

* [Handling and throwing exceptions in .NET | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/standard/exceptions/)
    
* [C# 10 in a Nutshell: The Definitive Reference](https://www.amazon.com/C-10-Nutshell-Definitive-Reference/dp/1098121953)
