Basics of Exception Handling
Avoid catching generic exceptions like Exception
unless absolutely necessary. Always prefer catching specific exception types.
Using Try/Catch
C# Example
Copy to clipboard
try {
// Code that may throw exceptions
} catch (IOException ex) {
Console.WriteLine($"I/O error: {ex.Message}");
} catch (UnauthorizedAccessException ex) {
Console.WriteLine($"Access error: {ex.Message}");
}
Finally Blocks
Use finally
blocks to guarantee resource cleanup regardless of exceptions.
FileStream file = null;
try {
file = new FileStream("file.txt", FileMode.Open);
// work with file
} catch (IOException ex) {
Console.WriteLine(ex.Message);
} finally {
file?.Close(); // ensures resource release
}
Using IDisposable Objects
using (var file = new FileStream("file.txt", FileMode.Open)) {
// Work with the file
} // Automatically disposed
Logging Exceptions
try {
// risky code
} catch (Exception ex) {
Logger.Error(ex, "An error occurred in method X");
}
Custom Exceptions
public class CustomException : Exception {
public CustomException(string message) : base(message) { }
}
// Usage
throw new CustomException("A specific error occurred");
Async Exception Handling
try {
await SomeAsyncMethod();
} catch (Exception ex) {
Console.WriteLine($"Async exception: {ex.Message}");
}
Exception Propagation Across Methods
Handle exceptions at the level where they make sense. Propagate upwards using throw
if a method cannot handle them meaningfully.
public void MainMethod() {
try{
SpecificMethod();
} catch (Exception ex){
Console.WriteLine($"Handled in MainMethod: {ex.Message}");
}
}
public void SpecificMethod() {
HelperMethod(); // may throw
}
public void HelperMethod() {
throw new InvalidOperationException("Something went wrong");
}
Unit Testing Exceptions
Write unit tests to verify exception handling works as expected.