Exception handling is a critical aspect of robust software development. It allows developers to manage and respond to runtime errors gracefully, ensuring that the application can recover or fail gracefully without crashing unexpectedly.
Key Concepts
- Exceptions: An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.
- Try-Catch Block: Used to handle exceptions. Code that might throw an exception is placed inside a
try
block, and exception handling code is placed inside one or morecatch
blocks. - Finally Block: A
finally
block contains code that is always executed, regardless of whether an exception was thrown or caught. - Throwing Exceptions: You can throw exceptions using the
throw
keyword. - Custom Exceptions: You can create your own exception classes to handle specific error conditions in your application.
Try-Catch Block
The try-catch
block is the fundamental construct for handling exceptions in C#. Here is the basic syntax:
try { // Code that may throw an exception } catch (ExceptionType1 ex) { // Code to handle ExceptionType1 } catch (ExceptionType2 ex) { // Code to handle ExceptionType2 } finally { // Code that will always execute }
Example
using System; class Program { static void Main() { try { int[] numbers = { 1, 2, 3 }; Console.WriteLine(numbers[5]); // This will throw an IndexOutOfRangeException } catch (IndexOutOfRangeException ex) { Console.WriteLine("An error occurred: " + ex.Message); } finally { Console.WriteLine("This block is always executed."); } } }
Explanation
- Try Block: Contains code that might throw an exception.
- Catch Block: Catches and handles the specific exception (
IndexOutOfRangeException
in this case). - Finally Block: Contains code that will always execute, regardless of whether an exception was thrown or not.
Throwing Exceptions
You can throw exceptions using the throw
keyword. This is useful when you want to signal an error condition explicitly.
Example
using System; class Program { static void Main() { try { ValidateAge(15); } catch (ArgumentException ex) { Console.WriteLine("An error occurred: " + ex.Message); } } static void ValidateAge(int age) { if (age < 18) { throw new ArgumentException("Age must be 18 or older."); } } }
Explanation
- ValidateAge Method: Throws an
ArgumentException
if the age is less than 18. - Main Method: Calls
ValidateAge
and catches theArgumentException
.
Custom Exceptions
You can create custom exception classes to handle specific error conditions in your application.
Example
using System; class InvalidAgeException : Exception { public InvalidAgeException(string message) : base(message) { } } class Program { static void Main() { try { ValidateAge(15); } catch (InvalidAgeException ex) { Console.WriteLine("An error occurred: " + ex.Message); } } static void ValidateAge(int age) { if (age < 18) { throw new InvalidAgeException("Age must be 18 or older."); } } }
Explanation
- InvalidAgeException Class: A custom exception class that inherits from
Exception
. - ValidateAge Method: Throws an
InvalidAgeException
if the age is less than 18. - Main Method: Calls
ValidateAge
and catches theInvalidAgeException
.
Practical Exercises
Exercise 1: Basic Exception Handling
Task: Write a program that takes two integers as input and divides them. Handle any potential exceptions that might occur.
Solution:
using System; class Program { static void Main() { 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 ex) { Console.WriteLine("Input must be a valid integer."); } catch (DivideByZeroException ex) { Console.WriteLine("Cannot divide by zero."); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); } finally { Console.WriteLine("Program execution completed."); } } }
Exercise 2: Custom Exception
Task: Create a custom exception called NegativeNumberException
and use it to handle cases where a negative number is input.
Solution:
using System; class NegativeNumberException : Exception { public NegativeNumberException(string message) : base(message) { } } class Program { static void Main() { try { Console.Write("Enter a positive number: "); int num = int.Parse(Console.ReadLine()); if (num < 0) { throw new NegativeNumberException("Number must be positive."); } Console.WriteLine("You entered: " + num); } catch (NegativeNumberException ex) { Console.WriteLine("An error occurred: " + ex.Message); } catch (FormatException ex) { Console.WriteLine("Input must be a valid integer."); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); } finally { Console.WriteLine("Program execution completed."); } } }
Common Mistakes and Tips
- Not Catching Specific Exceptions: Always catch specific exceptions before catching the general
Exception
class. - Overusing Exceptions: Use exceptions for exceptional conditions, not for regular control flow.
- Ignoring Exceptions: Always handle exceptions appropriately. Ignoring them can lead to unexpected behavior and difficult-to-debug issues.
Conclusion
Exception handling is a vital part of writing robust and maintainable C# applications. By understanding and using try-catch
blocks, throwing exceptions, and creating custom exceptions, you can ensure that your application can handle errors gracefully and continue to function correctly. In the next module, we will explore more control structures, such as loops and switch statements, to further enhance your programming skills.
C# Programming Course
Module 1: Introduction to C#
- Introduction to C#
- Setting Up the Development Environment
- Hello World Program
- Basic Syntax and Structure
- Variables and Data Types
Module 2: Control Structures
Module 3: Object-Oriented Programming
- Classes and Objects
- Methods
- Constructors and Destructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
Module 4: Advanced C# Concepts
- Interfaces
- Delegates and Events
- Generics
- Collections
- LINQ (Language Integrated Query)
- Asynchronous Programming
Module 5: Working with Data
Module 6: Advanced Topics
- Reflection
- Attributes
- Dynamic Programming
- Memory Management and Garbage Collection
- Multithreading and Parallel Programming