In many cases, you can use existing exception classes from the .NET Framework Class Library to indicate exceptions that occur in your programs. In some cases, however, you might wish to create new exception classes specific to the problems that occur in your programs. User-defined exception classes should derive directly or indirectly from class Exception
of namespace System
. When you create code that throws exceptions, they should be well documented, so that other developers who use your code will know how to handle them.
Associating each type of malfunction with an appropriately named exception class improves program clarity.
Before creating a user-defined exception class, investigate the existing exceptions in the .NET Framework Class Library to determine whether an appropriate exception type already exists.
NegativeNumberException
Figures 13.6–13.7 demonstrate a user-defined exception class. NegativeNumber-Exception
(Fig. 13.6) represents exceptions that occur when a program performs an illegal operation on a negative number, such as attempting to calculate its square root. According to Microsoft’s “Best Practices for Handling Exceptions” (bit.ly/Exceptions-BestPractices
), user-defined exceptions should typically extend class Exception
, have a class name that ends with Exception
and define three constructors:
a parameterless constructor,
a constructor that receives a string
argument (the error message), and
a constructor that receives a string
argument and an Exception
argument (the error message and the inner-exception object).
Defining these three constructors makes your exception class more flexible, allowing other programmers to easily use and extend it.
NegativeNumberException
s most frequently occur during arithmetic operations, so it seems logical to derive class NegativeNumberException
from class ArithmeticException
. However, class ArithmeticException
derives from class SystemException
—the category of exceptions thrown by the CLR. Per Microsoft’s best practices for exception handling, user-defined exception classes should inherit from Exception
rather than SystemException
. In this case, we could have used the built-in ArgumentOutOfRangeException
class (introduced in Chapter 10), which is recommended in the best practices for invalid argument values. We create our own exception type here simply for demonstration purposes.
NegativeNumberException
Class SquareRootTest
(Fig. 13.7) demonstrates our user-defined exception class. The app enables the user to input a numeric value, then invokes method SquareRoot
(lines 40–52) to calculate the square root of that value. To perform this calculation, SquareRoot
invokes class Math
’s Sqrt
method, which receives a double
value as its argument. Normally, if the argument is negative, method Sqrt
returns NaN
. In this program, we’d like to prevent the user from calculating the square root of a negative number. If the numeric value that the user enters is negative, method SquareRoot
throws a NegativeNumberException
(lines 45–46). Otherwise, SquareRoot
invokes class Math
’s method Sqrt
to compute the square root (line 50).
When the user inputs a value, the try
statement (lines 14–34) attempts to invoke SquareRoot
using the value input by the user. If the user input is not a number, a Format-Exception
occurs, and the catch
block in lines 25–29 processes the exception. If the user inputs a negative number, method SquareRoot
throws a NegativeNumberException
(lines 45–46); the catch
block in lines 30–34 catches and handles this type of exception.