Professional Documents
Culture Documents
Exception
Exception
Exception
Handling
Introduction
• Bugs: This is, simply put, an error on the part of the programmer. For example, assume
you are programming with unmanaged C++. If you make calls on a NULL pointer or fail to
delete allocated memory (resulting in a memory leak), you have a bug.
• User errors: Unlike bugs, user errors are typically caused by the individual running your
application, rather than by those who created it. For example, an end user who enters a
malformed string into a text box could very well generate an error if you fail to handle
this faulty input in your code base.
• Exceptions: Exceptions are typically regarded as runtime anomalies that are difficult, if
not impossible, to account for while programming your application. Possible exceptions
include attempting to connect to a database that no longer exists, opening a corrupted
file, or contacting a machine that is currently offline. In each of these cases, the
programmer (and end user) has little control over these “exceptional” circumstances.
• The Role of .NET Exception Handling
Prior to .NET, error handling under the Windows operating system was a confused
mishmash of techniques. Many programmers rolled their own error handling logic
within the context of a given application. For example, a development team may
define a set of numerical constants that represent known error conditions, and
make use of them as method return values. The following partial C code:
• Also, many C++ COM developers (and indirectly, many VB6 COM developers) have
made use of a small set of standard COM interfaces (e.g., ISupportErrorInfo,
IErrorInfo, ICreateErrorInfo) to return meaningful error information to a COM
client.
• In order to put an end to this madness, the .NET platform provides a standard
technique to send and trap runtime errors: structured exception handling (SEH).
• The advantage of this approach is that developers now have a unified approach
to error handling, which is common to all languages targeting the .NET universe.
The syntax is used to throw and catch exceptions across assemblies and machine
boundaries is identical.
• The Atoms of .NET Exception Handling
Programming with structured exception handling involves the use of four
interrelated entities:
A class type that represents the details of the exception that occurred.
A member that throws an instance of the exception class to the caller.
A block of code on the caller’s side that invokes the exception-prone
member .
A block of code on the caller’s side that will process (or catch) the exception
should it occur .
The C# programming language offers four keywords (try, catch, throw, and
finally) that allow you to throw and handle exceptions. The type that
represents the problem at hand is a class derived from System.Exception .
• The System.Exception Base Class
All user- and system-defined exceptions ultimately derive from the System.Exception base class
(which in turn derives from System.Object). Note that some of these members are virtual and may
thus be overridden by derived types:
The .NET base class libraries define many classes derived from System.Exception. For example, the
System namespace defines core error objects such as
ArgumentOutOfRangeException,
IndexOutOfRangeException,
StackOverflowException, and so forth.
Other namespaces define exceptions that reflect the behavior of that namespace (e.g.,
System.Drawing.Printing defines printing exceptions, System.IO defines IO-based exceptions,
System.Data defines database-centric exceptions, and so forth).
• Application-Level Exceptions
(System.ApplicationException)
The System.SystemException base class represents exceptions thrown from the CLR, you assume
that you should derive your custom exceptions from the System.Exception type. While you the best
practice dictates that you instead derive from the System.ApplicationException type:
When you handle an exception deriving from System.ApplicationException, you can assume the
exception was raised by the code base of the executing application, rather than by the .NET base
class libraries.
• Building Custom Exception
Best practice
• Derive from Exception / ApplicationException
• Is marked with the [System.Serializable] attribute
• Defines a default constructor
• Defines a constructor that sets the inherited Message property
• Defines a constructor to handle “inner exceptions”
• Defines a constructor to handle the serialization of your type
• Processing Multiple Exceptions
In its simplest form, a try block has a single catch block. In reality, you often run into
a situation where the statements within a try block could trigger numerous
possible exceptions. When authoring multiple catch blocks, programmer must be
aware that when an exception is thrown, it will be processed by the “first available”
catch.
• Generic catch Statements
C# also supports a “generic” catch scope that does not explicitly receive the exception object
thrown by a given member:
static void Main(string[] args) {
...
try {
for(int i = 0; i < 10; i++)
myCar.Accelerate(10);
}
catch {
Console.WriteLine("Something bad happened...");
}
...
}
• Rethrowing Exceptions
It is permissible for logic in a try block to rethrow an exception up the call stack to
the previous caller. To do so, simply make use of the throw keyword within a
catch block. This passes the exception up the chain of calling logic, which can be
helpful if the catch block is only able to partially handle the error at hand:
static void Main(string[] args) {
...
try {
// Speed up car logic...
}
catch(CarIsDeadException e)
{ throw e; }
...
}
• The Finally Block
A try/catch scope may also define an optional finally block, this block is to ensure
that a set of code statements will always execute, exception (of any type) or not.