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.
