Languages - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Languages arrow The Aerial View of Exceptions
The Aerial View of Exceptions
By DevSource

Rate This Article: Add This Article To:

We all use exceptions, but a high-level understanding makes exception throwing and handling much more effective.

In this article we’ll talk about exceptions. As implied by the name, exceptions are unexpected events that make a program unable to perform its duties in a logical manner. Exception handling empowers you to handle these little surprises rationally.

Let’s suppose you want to use the FileStream class and you try to call its Read method. The FileStream.Read method returns an integer that has the number of bytes read from the underlying source of data. If an abnormal condition occurs, such as the data being inaccessible due to a hardware failure, this method will throw an exception of the type IOException.

ADVERTISEMENT

Exception handling should not be used to handle usual or normal errors from which the program is able to easily recover. In the previous example, the caller of the FileStream.Read method expected to receive the number of bytes read. This number may be less than the number of bytes requested if end-of-file had been reached, but the caller would be expected to handle this condition. However, the caller would not be expected to handle an abnormal condition like the data source not being present when the read is attempted or some type of hardware failure when trying to read from the data source.

After a serious error, the calling method would then “catch” an exception of type IOException and could make a decision to “throw” it back to another level (its caller) or handle the exception itself. Later on, we will discuss the different ways you can go once you “catch” an exception.

Returning an error code to the calling method and allowing the caller to figure out a solution based on the returned value has always been the basic approach to handling an error. However, several problems with this approach come to mind:

There is no guarantee that the caller will check the error code, since the error handling happens outside the scope of the called method.

The method does not have enough data to handle the error. That is, the error may be out of the realm of the method that receives the error.

The error handling code needs to be every place that the method is called, so error handling cannot be localized.

The error may occur under several layers of the code path. This creates a problem in that you must know which method handles which errors, and how much information each layer of code should have regarding the next layer.

Without using exceptions, error conditions are checked and handled within the logic of the calling code. The capability to read, and subsequently maintain the code is hampered. The reason it’s hampered is because error detection and recovery code is mixed with the logic of the calling code itself.

Maintenance is virtually impossible. Each time a new error is detected that might occur in the called method, the calling code must be updated to handle this new kind of error.

Because of these problems, the best error-handling subsystem would have to be outside the normal flow of execution; a system that could discover an error and return the program to its last known good state. A good state is an area in the code where you can return and continue working while keeping the integrity of the system after receiving an unexpected error condition. In addition, the error-handling subsystem would allow the programmer to localize the error handling code so all errors of the same type could be pinpointed in one place in the system in order to avoid handling them over and over again. Consequently, this makes the code easier to maintain.

Tip: In programming, a good state is an area in the code where you can return and continue working while keeping the integrity of the after receiving an unexpected error condition. <Editor: Please make this short paragraph a tip or sidebar.>

Exception handling is built on all the premises listed above. As the developer, all you must do is tell the system what kinds of errors you are able to handle in the context of the code that you are writing. This code should be bracketed in a try statement: For instance, let’s say you write a method to create a bitmap image from a disk file. You (the developer of this method) would call that method and pass the name of the file used. If that file is corrupted or nonexistent, the method you called might decide the error is outside the realm of its capability. It would catch the error and throw it back to the calling method. You, the caller, could then choose at that layer what you would do with the error. You might choose to throw the exception back up to another layer, or you may decide that you have enough data to suitably process the error. The idea is to have each layer of code continuing to throw the exception back up to yet another layer of code until it’s handled properly. In this way, exception handling gives a flexible and productive means of error-handing.

Exception handling is not new to .NET. It has been around a while in various forms, whether directly supported by the language (Borland C++, Microsoft Visual C++, Borland Delphi, etc.) or home-grown by the programmer (for example, with ANSI C). Luckily for us, the designers of .NET chose to incorporate a very easy to use, flexible, yet powerful implementation of exception handling. If you wanted to program in C, you would call setjmp() to bookmark a place in your code and, if needed, call longjmp() to go back to that place if an unexpected error happened. Then, all local variables previously created on the stack would be automatically cleaned up by simply moving the stack pointer to the site marked with the setjmp() call. That’s OK for simple data types, but when you have complex data types like .NET objects, cleaning up becomes much more complicated. .NET’s implementation of exception handling makes the chore of cleaning up and returning the objects created obsolete, because it is automatically handled for you.

Tip: The Exception class is the superclass of all exceptions in the .NET language. Only objects that are instances of this class (or of one of its subclasses) are thrown by the .NET CLR or can be thrown by the .NET throw statement. Similarly, only this class or one of its subclasses can be the argument type in a catch clause.

An Exception class contains a snapshot of the execution stack of its thread at the time it was created. It can also contain a message string that gives more information about the error. <Editor: Please make the two previous paragraphs a tip or sidebar.>

As previously mentioned, .NET equips you with a smooth, direct way of dealing with exceptions. The system will simply throw only an instance of the Exception class (or one of its subclasses). When you are writing your .NET application, use the keyword try to communicate to the system everything you are going to attempt to get done as a group of related methods. That group of methods is labeled the try block. You in turn use the keyword catch to alert the system of what kinds of exceptions you are going to handle. That group of methods is labeled the catch block. In the catch block, you designate the type of exception you are trying to catch and what you want to do in case an exception of that type is thrown. You can only designate a class that is of type Exception (or a subclass of Exception). Of course, situations will arise where you will want certain code executed regardless of whether or not an exception was caught. This code is put in a finally block. Let me show you an example of these keywords in action:

    try
    {
        // try some things here
        // try some more things…
    }
    catch(  SomeKindOfExceptionClass ExceptionVariable )
    {
        // do what you want to do here upon catching the
        // exception
    }
    finally
    {
        // this code will execute whether or not an exception is
        // thrown from the code in the try block
    }

.NET also allows you to easily throw your own exceptions from your own methods. As you define a method, you state that the method can throw a certain class of exception.

    public void YourMethod( int i ) throws IOException
    {
        // your code
    }

This statement tells .NET that your method can throw an IOException as well as any of its subclasses. If you try to throw a class that is not a subclass of IOException, you will get an error when you try to compile your application—a handy thing when you are writing a generic method and meet up with an error that you think the caller will want to handle. You can simply catch the exception and throw it back to the caller. If you desire to throw more than one type of exception, you will need to separate them with commas.

    public void yourMethod2( int i )  throws IOException,
          ArgumentException
    {
        // your code
    }

Lastly, the thing I want to touch on here is the ability you have to easily create your own exception classes. You declare the exception class like you would any other class and, as mentioned previously, tell the compiler what methods are allowed to throw these exceptions.

Conclusion

Benefits abound in exception handling. Because .NET allows you to implement try/catch blocks when you call a method that has the capability to throw an exception, your programs are considered more bulletproof.

Error handling is executed in the proper context because it is done only by a method that has enough data to correctly handle the error condition. All alternative methods that catch the exception in question keep on throwing the exception until the method that is able to handle the error condition catches it.

Maintenance is simple because your programs are easier to read, due to the fact that error-handling code for each particular type of exception can be pinpointed to one area of the system.

Checking for errors and recovery from errors is more extensive than maintenance because it handles not only expected error conditions, but the occasional abnormal conditions as well.




Discuss The Aerial View of Exceptions
 
>>> Be the FIRST to comment on this article!
 

 
 
>>> More Languages Articles          >>> More By DevSource
 



Microsoft's Future: A Chat With Their CTO, Barry Briggs

Play Video >

All Videos >

Julia explores the Robotics Studio!

Read now >

Messages to Bill Gates!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.