Custom Exceptions in C#
In C# programming, an exception refers to an error that occurs during the execution of a program. However, in real-world applications, sometimes the built-in exceptions are not enough to clearly describe the problem; that is why we need to use custom exceptions. They are also called user-defined exceptions.
A custom exception allows us to define and manage application-specific errors in a clearer, more meaningful, and controlled way.
What is a Custom Exception in C#?
A custom exception is a user-defined class that inherits from the base System.Exception class (or a derived class). It enables developers to handle application-specific errors robustly and in a structured way.
How to Create a Custom Exception in C#
To create a custom exception class in C#, follow these steps −
- Create a new class that inherits from the Exception class.
- Define constructors (default, message-based, and with inner exception).
- Add custom properties or methods for additional information. It is optional.
- Use the try, catch and throw keywords to throw and catch the custom exception.
using System;
public class MyCustomException : Exception {
public MyCustomException() { }
public MyCustomException(string message)
: base(message) { }
public MyCustomException(string message, Exception innerException)
: base(message, innerException) { }
}
Why Use Custom Exceptions in C#?
We use custom exceptions to create our own exception classes that are helpful when you need to −
- Represent specific business logic errors (e.g., InvalidAge, UserNotFound, LowBalance).
- Make our exception handling more readable and organized.
- Add extra information like error codes, invalid values, or timestamps.
- Differentiate application errors from system errors.
- Provide a consistent exception structure across your application.
Example: Custom Exception in C#
In the following example, we create a user-defined exception for validating a person's age.
using System;
public class InvalidAgeException : Exception {
public InvalidAgeException(string message)
: base(message) { }
}
class Program {
static void ValidateAge(int age) {
if (age < 18){
throw new InvalidAgeException("Age must be 18 or older to register.");
}
Console.WriteLine("Registration successful!");
}
static void Main(){
try {
ValidateAge(15);
}
catch (InvalidAgeException ex) {
Console.WriteLine($"Custom Exception: {ex.Message}");
}
}
}
Following is the output −
Custom Exception: Age must be 18 or older to register.
Example: Adding Custom Properties to Exceptions
We can enhance our custom exception class by adding extra properties such as an error code or the invalid value.
using System;
public class InvalidAgeException : Exception {
public int AgeValue { get; }
// adding custom property
public InvalidAgeException(string message, int age)
: base(message) {
AgeValue = age;
}
}
class Program {
static void ValidateAge(int age) {
if (age < 18) {
throw new InvalidAgeException("You must be 18 or older.", age);
}
Console.WriteLine("Age is valid!");
}
static void Main() {
try {
ValidateAge(15);
}
catch (InvalidAgeException ex) {
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine($"Invalid Age Entered: {ex.AgeValue}");
}
}
}
Following is the output −
Error: You must be 18 or older. Invalid Age Entered: 15
C# Custom Exception with Inner Exception
In many situations, one exception can cause another. The InnerException property in C# helps you trace the original error that led to the current exception. It's useful for understanding the root cause of a problem while debugging.
using System;
public class FileProcessingException : Exception {
public FileProcessingException(string message, Exception inner) : base(message, inner) { }
}
class Program {
static void ProcessFile(){
try {
throw new NullReferenceException("File data is missing.");
}
catch (NullReferenceException ex) {
throw new FileProcessingException("Error while processing the file.", ex);
}
}
static void Main() {
try {
ProcessFile();
}
catch (FileProcessingException ex){
Console.WriteLine($"Custom Exception: {ex.Message}");
Console.WriteLine($"Inner Exception: {ex.InnerException.Message}");
}
}
}
Following is the output −
Custom Exception: Error while processing the file. Inner Exception: File data is missing.
Advantages of Custom Exceptions
Following are the advantages of custom exception −
- Provide clear and specific error messages.
- Help in better debugging and maintenance.
- Improve readability and structure of error-handling code.
- Allow custom logging and error reporting.
Buit-in Exception vs Custom Exception
Following is the difference between built-in and custom exceptions −
| Built-in Exceptions | Custom Exceptions |
|---|---|
| This is provided by .NET Framework (e.g., NullReferenceException, IndexOutOfRangeException). | It defined by the user for specific business rules or application needs. |
| It uses for General-purpose error handling. | It represents domain-specific error conditions. |
| It does not have extra properties after standard exception info. | It can include additional fields and methods. |
Conclusion
Custom exceptions in C# give us advantages to define meaningful, domain-specific errors that make our code cleaner, safer, and easy to debug. It is derived from the exception class, and by using it, we can build robust error-handling systems customized to our application's needs.