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.

Advertisements