Basics of Robust Exception Handling in C#: Using try-catch-finally

In application development, preparing for unexpected errors (exceptions) is essential. Whether it is a file load failure, network disconnection, or an invalid calculation, if you do not handle these issues properly, your application will crash.

In C#, you can use the try-catch-finally syntax to catch these exceptions and perform appropriate error handling or resource cleanup. Here, I will explain the basics of exception handling using a task progress rate calculation as an example.

目次

Basic Structure of try-catch-finally

The basic structure of exception handling consists of three blocks:

  • try: Write the code where an exception might occur.
  • catch: Catch the occurred exception and perform error recovery or display an error message.
  • finally: Write code that must be executed regardless of whether an exception occurred or not (such as releasing resources).

Practical Code Example: Handling Division by Zero

The following code calculates the progress rate from the number of completed tasks in a project. It shows how to properly handle a “division by zero” error that occurs if the “Total Tasks” is 0 (e.g., before a project starts).

using System;

namespace ProjectManagement
{
    class Program
    {
        static void Main()
        {
            // Scenario:
            // We want to calculate the progress rate of a project.
            // However, due to data issues, "Total Tasks" might be 0.

            int totalTasks = 0;      // Total tasks (Should ideally be 1 or more)
            int completedTasks = 5;  // Completed tasks

            try
            {
                // An exception might occur here.
                // Dividing integers where the denominator is 0 throws a DivideByZeroException.
                Console.WriteLine("Starting calculation...");
                
                int progressRate = (completedTasks * 100) / totalTasks;
                
                Console.WriteLine($"Progress Rate: {progressRate}%");
            }
            catch (DivideByZeroException ex)
            {
                // Specific handling when division by zero occurs
                Console.Error.WriteLine("Error: Cannot calculate progress because total tasks is 0.");
                // Write log output processing here if needed
                // Console.WriteLine(ex.Message); 
            }
            catch (Exception ex)
            {
                // Generic handling to catch all other unexpected exceptions
                Console.Error.WriteLine($"An unexpected error occurred: {ex.Message}");
            }
            finally
            {
                // Block that always executes regardless of exceptions
                // Perform tasks like closing database connections or releasing file handles here.
                Console.WriteLine("Ending calculation process.");
            }
        }
    }
}

Execution Result

Starting calculation...
Error: Cannot calculate progress because total tasks is 0.
Ending calculation process.

Technical Points and Precautions

1. Order of Catching Exceptions

catch blocks are evaluated from top to bottom. Therefore, you must write more specific exceptions (derived classes) first, and write the generic Exception class last. If you write Exception first, it will catch all exceptions, and the specific logic for errors like DivideByZeroException will not run.

2. Difference Between Integers and Floating-Point Numbers

In C#, division by zero throws an exception only for integer types (int, long, etc.). If you perform division by zero with floating-point types (double, float), no exception is thrown; instead, the result becomes Infinity or NaN (Not a Number).

// Case of double type
double total = 0.0;
double current = 10.0;
double result = current / total; // No exception, result is Infinity

3. Do Not Ignore Exceptions (Swallowing)

You should avoid leaving a catch block empty (known as “swallowing exceptions”). This hides the fact that an error occurred, making it extremely difficult to find the cause of bugs. At a minimum, you should output to a log, or if the process cannot continue, design the code to re-throw the exception (throw;).

Summary

By using try-catch-finally appropriately, you can return proper feedback to users without crashing the application, even when unexpected errors occur. Considering not just the “happy path” (normal execution) but also “error cases” is an essential requirement for ensuring professional software quality.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次