Click here to Skip to main content
6,630,586 members and growing! (16,706 online)
Email Password   helpLost your password?
Languages » C# » General     Intermediate

Exception Handling in C# with the "Do Not Catch Exceptions That You Cannot Handle" rule in mind

By Michael Vanhoutte

Exception handling in C# with the "Do Not Catch Exceptions That You Cannot Handle" rule in mind.
C#, Windows, .NET, Visual Studio, Dev
Posted:28 Jun 2004
Updated:6 Jan 2006
Views:118,431
Bookmarked:53 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
35 votes for this article.
Popularity: 6.30 Rating: 4.08 out of 5
3 votes, 8.6%
1

2
5 votes, 14.3%
3
15 votes, 42.9%
4
12 votes, 34.3%
5

Introduction

Microsoft advices in several documents never to do try { ... } catch (Exception ex) { ... } if you don't rethrow the same exception. This document explains how you can attempt to comply to this .NET Framework design guidelines rule: Do Not Catch Exceptions That You Cannot Handle.

Background

After working with Visual Basic 6 error-handling for several years, .NET exception handling comes as a relief. Although it is a major improvement compared to on error goto statements, it does have some problems. Since there are already plenty of resources out there that explain exception handling, I won't do that in this document. Instead, I'll explain how I attempt to comply to one of the .NET Framework design guidelines rules: Do Not Catch Exceptions That You Cannot Handle.

Or in other words: You should never catch System.Exception or System.SystemException in a catch block because you could inadvertently hide run-time problems like Out Of Memory. Refer to the Improving .NET Application Performance and Scalability document on Patterns & Practices website for more information on this rule. An example of something you should not do:

try {
  intNumber = int.Parse(strNumber);
} catch (Exception ex) {
  Console.WriteLine("Can't convert the string to " + 
                             "a number: " + ex.Message);
}

I agree that most of the times you should let the exception propagate up the call stack. However, this doesn't always work for me. For example, suppose I have an unattended application that copies files from one directory to another (it's a stupid example, I know, I just want to prove my point). I want this application to continue working regardless of what goes wrong during the file-copy operation because I'm going to send an e-mail in the end informing the administrator of all the failures. However, I don't want the application to continue if it throws an OutOfMemoryException or a BadImageFormatException for example. This is the C# code of my little application:

static void Main(string[] args)
{
  string[] strFiles = 
      System.IO.Directory.GetFiles(@"C:\Temp");
  System.Collections.ArrayList objSuccesses = 
               new System.Collections.ArrayList();
  System.Collections.ArrayList objFailures = 
               new System.Collections.ArrayList();
  foreach (string strFile in strFiles) 
  {
    try 
    {
      // We're simply copying a file here. 

      // In a real application, 

      //something more complicated would happen...

      System.IO.File.Copy(strFile, strFile + ".new");
      objSuccesses.Add(strFile);
    } 
    catch (Exception ex) 
    {
      Console.WriteLine("Failed to copy the file: " + 
                                             ex.Message);
      objFailures.Add(strFile);
    }
  }
  // We could send an e-mail here informing an 

  // administrator of all failures...

}

If we follow Microsoft's guidelines then we have to catch only those exceptions that could be triggered by the File.Copy method. If you look in the .NET Framework's Class Library, you'll see that this is UnauthorizedAccessException, ArgumentException, ArgumentNullException, PathTooLongException, DirectoryNotFoundException, FileNotFoundException, IOException and NotSupportedException. If you ask me, catching all these exceptions individually is not doable. All I wanted to know is whether or not a file copy failed or not. It would be sufficient to only capture IOException, ArgumentException and NotSupportedException (because all the other exceptions derive from these three exceptions) but to know this I have to read the documentation again. I really don't want to go through that much trouble to simply copy a file.

The guideline assumes that we know all the exceptions that can be thrown by the task executed. Copying a file is a very simple operation that is properly documented by Microsoft. But what if we're using some third-party tool? The stability of our unattended tool depends on the quality of the documentation of this tool. If this third-party forgets to mention one of the exceptions that their tool throws in the documentation, then our unattended application could stop prematurely.

Also, suppose that we know all the exceptions that can be thrown by this tool and suppose that we write our code to handle all these exceptions individually. What happens if we start using a new version of this tool one day? This new version could have the exact same API, but could be throwing more detailed or other exceptions. We therefore need to compare all the exceptions thrown by this tool with the ones that we capture in our code. Again, not doable...

Also, suppose I wanted to use for example the Save method of the System.Drawing.Image class. This method doesn't even list any exceptions; so how can I possibly handle an exception thrown by this method according to the guideline? This method is supposed to save an image to disk; there are dozens of things that can go wrong.

The feature that is missing in C# according to me is the ability to catch all the exceptions except the critical ones. To me Critical exceptions are for example, Out Of Memory, or AppDomain Is Unloading. That's why I wrote a small static method that tests if the exception thrown is a critical one. If it is, the exception is rethrown (the application could also simply stop gracefully). If it isn't a critical exception, it is logged, swallowed and the application continues. This is the code of my IsCritical method:

public static bool IsCritical(Exception ex) 
{
  if (ex is OutOfMemoryException) return true;
  if (ex is AppDomainUnloadedException) return true;
  if (ex is BadImageFormatException) return true;
  if (ex is CannotUnloadAppDomainException) return true;
  if (ex is ExecutionEngineException) return true;
  if (ex is InvalidProgramException) return true;
  if (ex is System.Threading.ThreadAbortException) 
      return true;
  return false;
}

This is the code of the application while using the IsCritical method:

static void Main(string[] args)
{
  string[] strFiles = 
      System.IO.Directory.GetFiles(@"C:\Temp");
  System.Collections.ArrayList objSuccesses = 
                      new System.Collections.ArrayList();
  System.Collections.ArrayList objFailures = 
                      new System.Collections.ArrayList();
  foreach (string strFile in strFiles) 
  {
    try 
    {
      // We're simply copying a file here. 

      // In a real application, 

      // something more complicated would happen...

      System.IO.File.Copy(strFile, strFile + ".new");
      objSuccesses.Add(strFile);
    } 
    catch (Exception ex) 
    {
      if (IsCritical(ex)) throw;
      Console.WriteLine("Failed to copy the file: " + 
                                           ex.Message);
      objFailures.Add(strFile);
    }
 }
 // We could send an e-mail here informing 

 // an administrator of all failures...

}

If you think that using this IsCritical method is a good idea, please let me know. If you know a reason why it's a bad idea, please do let me know.

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

About the Author

Michael Vanhoutte


Member
I am a developer spending most of my time in C#, .NET 2.0 and Sql Server 2005. I am working for a Belgium company called Adam Software developing Asset Management Software. More information about my company and our software can be found at http://www.adamsoftware.net
Occupation: Team Leader
Location: Belgium Belgium

Other popular C# articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 29 (Total in Forum: 29) (Refresh)FirstPrevNext
QuestionHow do I catch Missing Method exceptions PinmemberDonRobb_45:47 4 Nov '09  
GeneralHow do I catch a missing method exceptions PinmemberDonRobb_45:44 4 Nov '09  
GeneralRe: How do I catch a missing method exceptions PinmemberMichael Vanhoutte21:53 4 Nov '09  
Generaluse a flag and finally to achieve this Pinmemberflorinlazar22:09 6 May '08  
Shouldn't something similar to this: http://blogs.msdn.com/florinlazar/archive/2008/05/06/8465197.aspx[^] work for your scenario(s) if all you need is to know if the try block completed with success or not?
Sign In·View Thread·PermaLink
GeneralI agree but... PinmemberJEstes9:45 19 Apr '07  
NewsCaution Pinmembermichael rempel12:38 17 Nov '06  
GeneralThis is not just a C# problem! PinmemberTatworth20:38 9 Apr '06  
GeneralHalf way there? Pinmembertiefling1:27 12 Jan '06  
GeneralWhich ones are really critical? Pinmemberejp100:27 12 Jan '06  
GeneralAnother Critical Exception PinmemberS3an3:18 13 Jun '05  
GeneralRe: Another Critical Exception PinmemberMichael Vanhoutte23:22 13 Jun '05  
GeneralNot acceptable for unattended apps. Pinmembervarnk4:02 9 Jul '04  
GeneralRe: Not acceptable for unattended apps. Pinmemberskjagini12:04 21 Oct '04  
GeneralRe: Not acceptable for unattended apps. Pinmemberzildjohn0113:04 10 Aug '05  
GeneralMy experiences with exceptions in MFC PinmemberNathan Holt at CCEI6:51 8 Jul '04  
GeneralRe: My experiences with exceptions in MFC PinmemberMichael Vanhoutte12:17 8 Jul '04  
GeneralRe: My experiences with exceptions in MFC PinmemberNathan Holt at CCEI6:07 9 Jul '04  
GeneralRe: My experiences with exceptions in MFC Pinsussbtj-agilent13:30 9 Jul '04  
GeneralA posible danger in your method, & something ms could do to help PinmemberNathan Holt at CCEI6:31 8 Jul '04  
GeneralRe: A posible danger in your method, & something ms could do to help PinmemberMichael Vanhoutte12:09 8 Jul '04  
GeneralMy opinion Pinmemberpopsickle13:34 7 Jul '04  
GeneralRe: My opinion PinmemberMichael Vanhoutte11:59 8 Jul '04  
GeneralRe: My opinion Pinmemberpopsickle9:41 11 Jul '04  
GeneralSome feedback Pinmemberjfos6:25 7 Jul '04  
GeneralRe: Some feedback PinmemberMichael Vanhoutte10:45 7 Jul '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 6 Jan 2006
Editor: Rinish Biju
Copyright 2004 by Michael Vanhoutte
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project