Exception Handling in the .NET Runtime

Exception handling is a fundamental aspect of robust software development in .NET. It allows your application to gracefully manage runtime errors and unexpected events, preventing crashes and providing a better user experience. The .NET runtime provides a structured mechanism for detecting, signaling, and responding to these exceptional conditions.

The Exception Class Hierarchy

All exceptions in .NET derive from the System.Exception class. This hierarchy allows for a fine-grained control over how exceptions are caught and handled. Key base classes include:

Throwing Exceptions

You can explicitly throw an exception using the throw keyword. This is typically done when a method encounters an error condition that it cannot handle itself.

Example: Throwing a custom exception


public class InvalidOperationError : Exception
{
    public InvalidOperationError(string message) : base(message) { }
}

public void ProcessData(int value)
{
    if (value < 0)
    {
        throw new InvalidOperationError("Value cannot be negative.");
    }
    // ... process data ...
}
            

Catching Exceptions

The try-catch block is used to handle exceptions. Code that might throw an exception is placed within the try block, and the potential exceptions are handled in the catch block(s).

Example: Catching a specific exception


try
{
    ProcessData(-10);
}
catch (InvalidOperationError ex)
{
    Console.WriteLine($"An error occurred: {ex.Message}");
}
catch (Exception ex) // Catch any other general exceptions
{
    Console.WriteLine($"An unexpected error occurred: {ex.ToString()}");
}
finally
{
    Console.WriteLine("This block always executes.");
}
            

The finally Block

The finally block is optional and contains code that will always execute, regardless of whether an exception was thrown or caught. It's commonly used for resource cleanup.

Tip: Use specific catch blocks for expected exceptions before a general catch (Exception ex) to ensure that your application handles known issues gracefully.

Uncaught Exceptions

If an exception is thrown and not caught by any catch block, the .NET runtime will typically terminate the current thread and, if it's the main thread, the application. An unhandled exception event is raised, which can be subscribed to for logging or other global error handling.

Warning: Uncaught exceptions are a sign of programming errors and should be investigated and addressed to improve application stability.

Exception Filters (C# 6 and later)

Exception filters allow you to specify a condition for a catch block. The block only executes if the condition evaluates to true.

Example: Using an exception filter


try
{
    // ... code that might throw an exception ...
}
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
    Console.WriteLine("Resource not found.");
}
            

Best Practices