Introduction to Error Handling in C#: try, catch, and finally

No matter how careful you are when writing C# code, things can and will go wrong — users enter bad input, files go missing, networks fail. That’s why error handling is so important. Rather than letting your program crash, you can catch and deal with errors gracefully.

This is where you’ll learn how to use try, catch, and finally to handle errors safely in C#. We’ll also explore best practices and simple examples to help you build reliable and user-friendly applications.


🧨 What Is an Exception?

An exception is an error that occurs at runtime — when your code is running, not compiling. If unhandled, it can crash your application.

Common examples:

  • Dividing by zero
  • Accessing a file that doesn’t exist
  • Parsing invalid user input

🧱 Basic Error Handling Structure

C# uses try, catch, and optionally finally to handle errors.

🔹 Syntax:

try
{
    // Code that might throw an exception
}
catch (Exception ex)
{
    // Code to run if an exception occurs
}
finally
{
    // Code that always runs (optional)
}

⚙️ Example: Basic try-catch

try
{
    int number = int.Parse("abc"); // This will throw FormatException
    Console.WriteLine(number);
}
catch (FormatException ex)
{
    Console.WriteLine("Invalid number format.");
}

💡 Use specific exception types like FormatException, DivideByZeroException, etc. instead of the generic Exception when possible.


🧼 finally Block

The finally block always runs — whether or not an exception occurred. It’s perfect for cleanup code, like closing files or database connections.

try
{
    Console.WriteLine("Opening connection...");
    // Simulate code that might fail
}
catch (Exception ex)
{
    Console.WriteLine("Something went wrong: " + ex.Message);
}
finally
{
    Console.WriteLine("Closing connection...");
}

Even if an error occurs, "Closing connection..." will still be printed.


💡 Multiple catch Blocks

You can catch different error types with multiple catch blocks:

try
{
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[5]); // Index out of bounds
}
catch (IndexOutOfRangeException)
{
    Console.WriteLine("That index doesn’t exist.");
}
catch (Exception ex)
{
    Console.WriteLine("General error: " + ex.Message);
}

🧠 Catch specific exceptions first, then a general Exception as a fallback.


⚠️ Common Exception Types

Exception TypeWhen It Happens
FormatExceptionParsing invalid strings (e.g., int.Parse("abc"))
DivideByZeroExceptionWhen dividing a number by zero
NullReferenceExceptionUsing a variable that’s null
FileNotFoundExceptionAccessing a missing file
IndexOutOfRangeExceptionInvalid array index

✅ Best Practices

  • ✅ Catch only the exceptions you can handle
  • ✅ Avoid empty catch blocks — log or respond meaningfully
  • ✅ Use finally for cleanup tasks
  • ✅ Don’t use exceptions for normal program flow
  • ✅ Consider logging tools for real-world applications (e.g., Serilog, NLog)

🧪 Quick Challenge

Write a program that:

  1. Asks the user to enter two numbers
  2. Divides the first by the second
  3. Catches divide-by-zero and format exceptions
  4. Always prints “Program complete” at the end
try
{
    Console.Write("Enter the first number: ");
    int num1 = int.Parse(Console.ReadLine());

    Console.Write("Enter the second number: ");
    int num2 = int.Parse(Console.ReadLine());

    int result = num1 / num2;
    Console.WriteLine("Result: " + result);
}
catch (FormatException)
{
    Console.WriteLine("Please enter valid numbers.");
}
catch (DivideByZeroException)
{
    Console.WriteLine("Cannot divide by zero.");
}
finally
{
    Console.WriteLine("Program complete.");
}

📚 Summary

KeywordPurpose
tryRun code that may throw an exception
catchHandle specific errors if they occur
finallyAlways run cleanup code (optional)

📬 Have a question about handling errors in your project, or want help debugging C# code? Reach out to us via our Contact Page — we’re happy to help learners build confidence through clarity.