15.02.2015 Views

C# 4 and .NET 4

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Catching exceptions ❘ 353<br />

➤<br />

arguments. Subclasses of System.SystemException include classes that represent both fatal <strong>and</strong><br />

nonfatal errors.<br />

System.ApplicationException — This class is important, because it is the intended base<br />

for any class of exception defined by third parties. If you define any exceptions covering error<br />

conditions unique to your application, you should derive these directly or indirectly from System<br />

.ApplicationException.<br />

Other exception classes that might come in h<strong>and</strong>y include:<br />

➤<br />

➤<br />

➤<br />

StackOverflowException — This exception is thrown when the area of memory allocated<br />

to the stack is full. A stack overflow can occur if a method continuously calls itself recursively.<br />

This is generally a fatal error, because it prevents your application from doing anything apart<br />

from terminating (in which case it is unlikely that even the finally block will execute). Trying<br />

to h<strong>and</strong>le errors like this yourself is usually pointless; instead, you should get the application to<br />

gracefully exit.<br />

EndOfStreamException — The usual cause of an EndOfStreamException is an attempt to read<br />

past the end of a file. A stream represents a flow of data between data sources. Streams are covered in<br />

detail in Chapter 24, “Networking.”<br />

OverflowException — An OverflowException is what happens if you attempt to cast an int<br />

containing a value of -40 to a uint in a checked context.<br />

The other exception classes shown in Figure 15-1 are not discussed here.<br />

The class hierarchy for exceptions is somewhat unusual in that most of these classes do not add any<br />

functionality to their respective base classes. However, in the case of exception h<strong>and</strong>ling, the common<br />

reason for adding inherited classes is to indicate more specific error conditions. There is often no need to<br />

override methods or add any new ones (although it is not uncommon to add extra properties that carry<br />

extra information about the error condition). For example, you might have a base ArgumentException class<br />

intended for method calls where inappropriate values are passed in, <strong>and</strong> an ArgumentNullException class<br />

derived from it, which is intended to h<strong>and</strong>le a null argument if passed.<br />

CaTChing eXCePTions<br />

Given that the .<strong>NET</strong> Framework includes a selection of predefined base class exception objects, how do you<br />

use them in your code to trap error conditions To deal with possible error conditions in <strong>C#</strong> code, you will<br />

normally divide the relevant part of your program into blocks of three different types:<br />

➤<br />

➤<br />

➤<br />

try blocks encapsulate the code that forms part of the normal operation of your program <strong>and</strong> that<br />

might encounter some serious error conditions.<br />

catch blocks encapsulate the code that deals with the various error conditions that your code might<br />

have encountered by working through any of the code in the accompanying try block. This place<br />

could also be used for logging errors.<br />

finally blocks encapsulate the code that cleans up any resources or takes any other action that<br />

you will normally want done at the end of a try or catch block. It is important to underst<strong>and</strong> that<br />

the finally block is executed whether or not an exception is thrown. Because the aim is that the<br />

finally block contains cleanup code that should always be executed, the compiler will flag an error<br />

if you place a return statement inside a finally block. For an example of using the finally block,<br />

you might close any connections that were opened in the try block. It is also important to underst<strong>and</strong><br />

that the finally block is completely optional. If you do not have a requirement for any cleanup code<br />

(such as disposing or closing any open objects), then there is no need for this block.<br />

So how do these blocks fit together to trap error conditions Here is how:<br />

1. The execution flow first enters the try block.<br />

2. If no errors occur in the try block, execution proceeds normally through the block, <strong>and</strong> when the<br />

end of the try block is reached, the flow of execution jumps to the finally block if one is present<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!