In C#, an exception is an object created (or thrown) when a particular exceptional error condition occurs. This object contains information that should help track down the problem. Although you can create your own exception classes (and you will be doing so later), .NET provides you with many predefined exception classes.
This section provides a quick survey of some of the exceptions available in the .NET base class library. Microsoft has provided a large number of exception classes in .NET- too many to provide a comprehensive list here. This class hierarchy diagram in Figure shows a few of these classes to give you a sense of the general pattern.
All the classes shown are part of the System namespace, except for IOException and the classes derived from IOException, which are part of the namespace System. 10. The System. 10 namespace deals with reading and writing data to files. In general, there is no specific namespace for exceptions. Exception classes should be placed in whatever namespace is appropriate to the classes that can generate them – hence IO-related exceptions are in the System. 10 namespace. You will find exception classes in quite a few of the base class namespaces.
The generic exception class, System. Exception, is derived from System. Object, as you would expect for a .NET class. In general, you should not throw generic System. Exception objects in your code, because they provide no specifics about the error condition.
Two important classes in the hierarchy are derived from System. Exception:
- System. SystemException – This class is for exceptions that are usually thrown by the .NET runtime or that are considered to be of a generic nature and might be thrown by almost any application. For example, StackOverflowException will be thrown by the .NET runtime if it detects the stack is full. However, you might choose to throw ArgumentException or its
sub classes in your own code, if you detect that a method has been called with inappropriate arguments. Subclasses of System. SystemException include classes that represent both fataland nonfatal errors.
- System. ApplicationException – This class is important, because it is the intended base for any class of exception defined by third parties. If you define any exceptions covering error conditions unique to your application, you should derive these directly or indirectly from System. ApplicationException.
Other exception classes that might come in handy include the following:
- StackOverflowException – This exception is thrown when the area of memory allocated to the stack is full.A stack overflow can occur if a method continuously calls itself recursively. This
is generally a fatal error, because it prevents your application from doing anything apart from terminating (in which case it is unlikely that even the finally block will execute). Trying to handle errors like this yourself is usually pointless; instead, you should get the application to gracefully exit.
- EndOfStreamException – The usual cause of an EndOfStreamException is an attempt to read past the end of a file.A stream represents a flow of data between data sources. Streams are covered .
- OverflowException – An OverflowException is what happens if you attempt to cast an int containing a value of -40 to a uint in a checked context.
The other exception classes shown in Figure 14-1 are not discussed here.
The class hierarchy for exceptions is somewhat unusual in that most of these classes do not add any functionality to their respective base classes. However, in the case of exception handling, the common reason for adding inherited classes is to indicate more specific error conditions. There is often no need to override methods or add any new ones (although it is not uncommon to add extra properties that carry extra information about the error condition). For example, you might have a base ArgumentException Class intended for method calls where inappropriate values are passed in, and an ArgumentNullException class derived from it, which is intended to handle a null argument if passed.