Understanding C# Exceptions

Exceptions in C# are runtime errors that occur during the execution of a program. They are handled using the try, catch, finally, and throw keywords. Proper exception handling ensures that a program can gracefully recover from errors or terminate safely, preventing data corruption or crashes.

Key Topics

What are Exceptions?

An exception is a problem that occurs during the execution of a program. When an exception occurs, the normal flow of the program is interrupted, and the runtime attempts to handle the error. If not handled, the program terminates. Examples of common exceptions include DivideByZeroException, NullReferenceException, and FileNotFoundException.

Handling Exceptions with Try-Catch

The try-catch block in C# is used to catch exceptions that occur during the execution of a program. You can handle multiple exceptions using multiple catch blocks, allowing different types of exceptions to be handled differently.

Example: Handling Exceptions

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            // Attempting to divide by zero
            int result = 10 / 0;
            Console.WriteLine("Result: " + result);
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }
}

Output:

Error: Attempted to divide by zero.
                        

Explanation: The try block attempts to divide by zero, which causes a DivideByZeroException. The catch block catches the exception and displays an error message without terminating the program abruptly.

The Finally Block

The finally block in C# is used to execute code regardless of whether an exception was thrown or caught. It is typically used for cleaning up resources, such as closing files or database connections.

Example: Using a Finally Block

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            // Attempt to parse a non-integer string
            int number = int.Parse("ABC");
            Console.WriteLine("Number: " + number);
        }
        catch (FormatException ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
        finally
        {
            Console.WriteLine("Finally block executed.");
        }
    }
}

Output:

Error: Input string was not in a correct format.
Finally block executed.
                        

Explanation: In this example, the try block attempts to parse a string that cannot be converted to an integer, throwing a FormatException. The finally block is executed after the catch block, ensuring that it runs regardless of whether an exception occurred.

Throwing Exceptions

You can explicitly throw exceptions using the throw keyword in C#. This is useful when you want to signal that an error has occurred based on certain conditions in your code.

Example: Throwing an Exception

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            ValidateAge(15);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }

    static void ValidateAge(int age)
    {
        if (age < 18)
        {
            throw new ArgumentException("Age must be at least 18.");
        }
        Console.WriteLine("Age is valid.");
    }
}

Output:

Error: Age must be at least 18.
                        

Explanation: The ValidateAge() method checks if the provided age is less than 18. If it is, an ArgumentException is thrown. The exception is caught in the try block, and an error message is displayed.

Creating Custom Exceptions

In C#, you can create custom exceptions by extending the Exception class. Custom exceptions are useful for providing more specific error information that pertains to your application.

Example: Creating a Custom Exception

using System;

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

class Program
{
    static void Main(string[] args)
    {
        try
        {
            CheckProduct("");
        }
        catch (InvalidProductException ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
    }

    static void CheckProduct(string product)
    {
        if (string.IsNullOrEmpty(product))
        {
            throw new InvalidProductException("Product name cannot be empty.");
        }
        Console.WriteLine("Product is valid.");
    }
}

Output:

Error: Product name cannot be empty.
                        

Explanation: The custom exception InvalidProductException is thrown if the provided product name is empty or null. The CheckProduct() method throws this exception, which is then caught and handled in the try-catch block.

Key Takeaways

  • Exceptions in C# are runtime errors that occur during program execution.
  • Use try-catch blocks to handle exceptions and prevent abrupt program termination.
  • The finally block is used to execute code regardless of whether an exception is thrown or caught.
  • You can explicitly throw exceptions using the throw keyword.
  • Custom exceptions can be created by extending the Exception class to provide more specific error messages.