Back to Curriculum

Exception Handling

📚 Lesson 8 of 15 ⏱️ 40 min

Exception Handling

40 min

C# uses try-catch-finally blocks for exception handling, enabling you to handle errors gracefully and prevent application crashes. try blocks contain code that might throw exceptions. catch blocks handle specific exception types. finally blocks execute cleanup code regardless of exceptions. Understanding exception handling enables robust applications. Exception handling is essential for production code.

Exceptions are objects that inherit from System.Exception, containing information about errors (message, stack trace, inner exception). Exception types indicate error categories (ArgumentException, NullReferenceException, etc.). Catching specific exception types enables targeted error handling. Understanding exceptions enables effective error management. Exceptions are the standard error mechanism in C#.

The 'using' statement ensures proper disposal of resources (files, database connections, etc.) by automatically calling Dispose() even if exceptions occur. 'using' is syntactic sugar for try-finally with Dispose(). IDisposable interface defines disposable resources. Understanding 'using' enables proper resource management. 'using' prevents resource leaks.

Custom exceptions can be created by inheriting from Exception, enabling domain-specific error types. Custom exceptions should include meaningful messages and follow naming conventions (end with 'Exception'). Custom exceptions enable clearer error communication. Understanding custom exceptions enables better error handling. Custom exceptions improve code clarity.

Exception handling best practices include catching specific exceptions (not Exception), not swallowing exceptions silently, logging exceptions, using finally for cleanup, and throwing meaningful exceptions. Understanding best practices enables professional error handling. Proper exception handling is critical for reliability.

Best practices include catching specific exception types, not catching Exception unless necessary, logging exceptions for debugging, using 'using' for resource management, and creating custom exceptions for domain-specific errors. Understanding exception handling enables robust applications. Exception handling is essential for production code.

Key Concepts

  • C# uses try-catch-finally blocks for exception handling.
  • Exceptions are objects that inherit from System.Exception.
  • The 'using' statement ensures proper disposal of resources.
  • Custom exceptions can be created by inheriting from Exception.
  • Catch specific exceptions, not the base Exception class.

Learning Objectives

Master

  • Using try-catch-finally blocks
  • Handling specific exception types
  • Using 'using' statement for resource management
  • Creating custom exceptions

Develop

  • Understanding error handling strategies
  • Designing robust error handling
  • Appreciating exception handling's role in reliability

Tips

  • Catch specific exceptions, not the base Exception class.
  • Use 'using' statement for resources that implement IDisposable.
  • Log exceptions for debugging and monitoring.
  • Don't swallow exceptions silently—handle or rethrow them.

Common Pitfalls

  • Catching Exception and swallowing it, hiding bugs.
  • Not using 'using' for resources, causing memory leaks.
  • Not logging exceptions, making debugging difficult.
  • Creating exceptions that are too generic, losing error context.

Summary

  • C# uses try-catch-finally for exception handling.
  • Exceptions are objects with error information.
  • The 'using' statement ensures resource disposal.
  • Custom exceptions enable domain-specific errors.
  • Understanding exception handling enables robust applications.

Exercise

Demonstrate exception handling with try-catch blocks and custom exceptions.

using System;

// Custom exception
public class InvalidAgeException : Exception
{
    public InvalidAgeException(string message) : base(message) { }
}

class Program
{
    static void ValidateAge(int age)
    {
        if (age < 0)
            throw new InvalidAgeException("Age cannot be negative");
        if (age > 150)
            throw new InvalidAgeException("Age seems unrealistic");
    }
    
    static void Main(string[] args)
    {
        // Basic exception handling
        try
        {
            int result = 10 / 0;
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Unexpected error: {ex.Message}");
        }
        finally
        {
            Console.WriteLine("Finally block always executes");
        }
        
        // Custom exception
        try
        {
            ValidateAge(-5);
        }
        catch (InvalidAgeException ex)
        {
            Console.WriteLine($"Validation error: {ex.Message}");
        }
        
        // Using statement for resource management
        using (var writer = new System.IO.StringWriter())
        {
            writer.WriteLine("This is a test");
            Console.WriteLine("Resource used and disposed");
        }
    }
}

Code Editor

Output