How to create a custom exception in C#
By FoxLearn 12/24/2024 8:59:39 AM 16
To create a custom exception in C#, you need to derive a class from the base Exception
class.
public class CustomException : Exception { // Constructor that takes a custom message public CustomException(string message) : base(message) { } // Parameterless constructor public CustomException() { } }
We create a new class CustomException
, which inherits from the Exception
class.
The constructor allows you to pass a custom error message, which is then passed to the base class (Exception
) constructor. This ensures that the error message is stored and can be accessed when the exception is thrown.
You can throw this exception just like any other built-in exception:
throw new SimpleCustomException("create a custom exception in c#");
When the exception is caught, it will display the name of the exception and the message:
CustomException: create a custom exception in c#
Why Use Custom Exceptions?
While it is possible to throw common exceptions like ArgumentException
or FormatException
, custom exceptions provide several advantages:
- Specificity: You can create highly specific exceptions for particular error conditions.
- Easier Logging: Custom exceptions allow for better control over logging and error monitoring. For example, a log system can easily filter out specific exception types, making it easier to track issues.
- Improved Error Handling: By defining custom exceptions, client code can catch and handle specific issues more appropriately. It allows the caller to make decisions based on the exact type of error.
Let’s consider an example where you want to parse a binary string, but you need to handle cases where the input string is invalid. Instead of using a generic ArgumentException
, we can define a custom exception called InvalidBinaryStringException
.
public class InvalidBinaryStringException : Exception { public InvalidBinaryStringException(string binaryString) : base($"Bad binary string: {binaryString}. Binary string must be 0's and 1's and the length must be a multiple of 8. Example: 00010001.") { } }
In this case, the custom exception takes the invalid binary string as a parameter and formats a detailed error message explaining the expected format.
We will create a class BinaryStringUtil
that will parse binary strings. If the binary string is invalid (e.g., it contains characters other than 0
or 1
or if its length isn’t a multiple of 8), the method will throw our custom InvalidBinaryStringException
.
using System; using System.Text.RegularExpressions; public class BinaryStringUtil { public static byte[] Parse(string binaryString) { // Check if binary string is valid if (binaryString.Length % 8 != 0 || Regex.IsMatch(binaryString, "[^01]")) { throw new InvalidBinaryStringException(binaryString); } // Parse binaryString into byte[] // For simplicity, this part is omitted return new byte[] { }; } }
The Parse
method checks:
- If the length of the binary string is a multiple of 8 (a valid binary string must be a multiple of 8 bits).
- If the string contains only
0
s and1
s, using a regular expression.
If the string is invalid, the InvalidBinaryStringException
is thrown with a detailed message indicating what went wrong and what the expected input should be.
You can now call the Parse
method and handle the exception when the input is invalid:
try { byte[] result = BinaryStringUtil.Parse("0101000x"); } catch (InvalidBinaryStringException ex) { Console.WriteLine(ex.Message); }
If an invalid binary string is passed, the exception will be caught, and the message will be displayed:
Bad binary string: 0101000x. Binary string must be 0's and 1's and the length must be a multiple of 8. Example: 00010001.
Why Not Use ArgumentException
or FormatException
?
You may wonder why we didn’t just use ArgumentException
or FormatException
for this case. While both of these exceptions would work in a general sense, using a custom exception provides several benefits:
- Clarity: It makes the error more specific. By catching
InvalidBinaryStringException
, client code can handle this error type separately from other generic exceptions. - Easy Identification: In a logging or monitoring system, it’s easier to track
InvalidBinaryStringException
than a generic exception type likeArgumentException
with a custom message. - Maintainability: If the format of the binary string changes or if more validations are added in the future, having a custom exception allows you to encapsulate that logic in one place.
To ensure that your custom exceptions are thrown correctly, you can write unit tests. Using the MSTest framework, you can test that the Parse
method throws the expected exception when the binary string is invalid.
using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class BinaryStringUtilTests { [DataRow("01")] [DataRow("0101000x")] [TestMethod] public void ParseTest_WhenBadBinaryString_ThrowsException(string binaryString) { Assert.ThrowsException<InvalidBinaryStringException>(() => BinaryStringUtil.Parse(binaryString)); } }
This test method uses the Assert.ThrowsException
method to verify that the InvalidBinaryStringException
is thrown when the Parse
method receives invalid data. It checks cases where the string is too short or contains invalid characters.