Click here to Skip to main content
15,884,177 members
Articles / Programming Languages / C#
Article

Practical .NET2 and C#2

Rate me:
Please Sign up or sign in to vote.
1.50/5 (9 votes)
3 Mar 20065 min read 26.4K   17   1
Exception management guidelines for use in C#.

TitlePractical .NET2 and C#2
AuthorPatrick Smacchia
PublisherParadoxalPress
PublishedJanuary 2006
ISBN0-9766132-2-0
PriceUSD 59.95 (ParadoxalPress price: USD 33.99)
Pages896
Websitehttp://www.practicaldot.net/ (Browse and download the 647 listings and sample chapters)

The following guidelines are excerpted from the book Practical .NET2 and C#2.

Contents

When should you consider throwing an exception?

The exception mechanism is generally well understood but quite often used improperly. The base principle is that an application which functions in a normal way should not throw exceptions. This forces us to define what an abnormal situation is. There are three types of abnormal situations:

  • Those which happen because of a problem with the execution environment but can be solved by a modification to this environment (missing file, invalid password, non-well-formed XML document, network unavailability, restricted security permissions…). Here, we are talking of business exceptions.
  • Those which happen because of an execution environment problem which cannot be solved. For example, memory hungry applications such as SQL Server 2005 may be limited to 2 or 3 GB of addressing space in a 32-bits Windows process. Here, we are talking of asynchronous exceptions from the fact that they are not related to the semantics of the code which raised it. To manage this type of a problem, you must use advanced CLR 2.0 features such as Constrained Execution Regions (CERs) and Critical Finalizers. This is essentially equivalent to treating such abnormal situations as normal! Be aware that only large servers which push the limits of its resources should encounter asynchronous exceptions and will need to use these advanced mechanisms.
  • Those which happen because of a bug, and which can only be solved by a patch which fixes the bug properly.

What to do in exception handlers?

When you catch an exception, you can envision three scenarios:

  • Either you are faced with a real problem, that you can address by fixing the conditions which cause the problem. For this, you may need new information (invalid password: ask the user to reenter the password...).
  • Or you are faced with a problem which you cannot resolve at this level. In this case, the only good approach is to re-throw the exception. It is possible that there may not be a proper exception handler, and in this case, you delegate the decision to the CLR runtime host. In console or windowed applications, the runtime host causes the whole process to terminate. Note that you can use the AppDomain.UnhandledException event which is triggered in this situation, in order to take over the termination of the process. You can take advantage of this ‘last chance’ to save your data (as with Word) without which this would definitely lead to data loss. In an ASP.NET context, an error processing mechanism is put in place.
  • In theory, a third scenario can be envisioned. It is possible that the exception that was caught represents a false alarm. In practice, this never happens.

You must not catch an exception to simply log it and then re-throw it. To log exceptions and the code that they have traversed, we recommend using less intrusive approaches such as the use of specialized events of the AppDomain class, or the analysis of the methods on the stack at the moment where the exception was thrown.

You must not release the resources that you have allocated when you catch an exception. Also, be aware that, in general, only unmanaged resources are susceptible of causing problems (such as memory leaks). This type of code to release resources must be placed in a finally block or in a Dispose() method. In C#, the finally blocks are often implicitly encapsulated in a using block which acts on objects implementing the IDisposable interface.

Where should you put exception handlers?

For a specific type of exception, asking this question comes down to asking yourself at which method depth this exception must be caught and what must be done about it. By method depth, we mean the number of calls embedded since the entry point (generally the Main() method). This means that the method representing the entry point is the least deep. The answer to these two questions depends on the semantics of an exception. Ask yourself for each type of exception, at which depth your code is more apt to be able to correct the conditions which have triggered the exception and resume the execution, or to be able to properly terminate the application.

Generally, the deeper a method is, the less it must catch custom exceptions. The reason is that custom exceptions often have a signification to the business of your application. Hence, if you develop a class library, you must let exceptions which are meant to the client application bubble outside of the library.

Exceptions vs. returned error code

You may be tempted to use exceptions instead of returning error codes in your methods, in order to indicate a potential problem. You must be careful, as the use of exceptions suffers from two major disadvantages:

  • The code is hard to read. In fact, to understand the code, you must manually do the work of the CLR, which consists in traversing the calls until you find an exception handler. Even if you properly separate your calls into layers, the code is still difficult to read.
  • Exception handling by the CLR is much more expensive in terms of performance than simply looking at an error code.

The fundamental rule mentioned at the beginning of this section can help you make this decision: an application which functions within normal conditions does not raise exceptions.

Never underestimate bugs whose consequences are caught by exception handlers

An abusive use of exceptions happen when we assume that, since we catch all exceptions, those provoked by eventual bugs will also be caught. We then assume that they will prevent the application from crashing. This reasoning does not take into account the fact that the main nuisances from bugs are from those which go uncaught, such as indeterminist, unexpected, or false results.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
Patrick Smacchia is a .NET MVP involved in software development for over 15 years. He is the author of Practical .NET2 and C#2, a .NET book conceived from real world experience with 647 compilable code listings. After graduating in mathematics and computer science, he has worked on software in a variety of fields including stock exchange at Société Générale, airline ticket reservation system at Amadeus as well as a satellite base station at Alcatel. He's currently a software consultant and trainer on .NET technologies as well as the author of the freeware NDepend which provides numerous metrics and caveats on any compiled .NET application.

Comments and Discussions

 
QuestionExceptions are evil - the old new thing.... Pin
ricoohh28-Apr-19 23:16
professionalricoohh28-Apr-19 23:16 
I am absolutely with you : an application, which functions in a normal way, should not throw exceptions!

I remember reading the article from Joel Spolsky:
13 – Joel on Software
He references to the well known Raymond Chen and two of his articles from 2004/2005:
Cleaner, more elegant, and wrong | The Old New Thing
Cleaner, more elegant, and harder to recognize | The Old New Thing

Maybe you covered these "thoughts" in your (no longer existing?) book.
Problems with Windows? re-boot.
Problems with Linux? be-root!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.