7

Possible Duplicate:
Catching specific vs. generic exceptions in c#

Here's an example method

private static void outputDictionaryContentsByDescending(Dictionary<string, int> list)
{
    try
    {
        //Outputs entire list in descending order
        foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value))
        {
            Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
        }
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

I would like to know what exception clause to use apart from just Exception and if there is an advantage in using more specific catch clauses.

Edit: O.k thanks everyone

Community
  • 1
  • 1
Elliot678
  • 338
  • 2
  • 6
  • 16

10 Answers10

7

Catching individual types of Exceptions in your statement will allow you to handle each in a different way.

A blanket rule for Exception may be useful for logging and rethrowing Exceptions, but isn't the best for actually handling Exceptions that you may be able to recover from.

try
{
    // open a file specified by the user
}
catch(FileNotFoundException ex)
{
    // notify user and re-prompt for file
}
catch(UnauthorizedAccessException ex)
{
    // inform user they don't have access, either re-prompt or close dialog
}
catch(Exception ex)
{
    Logger.LogException(ex);
    throw;
}
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
4

You should only really catch exceptions that you are expecting that code may throw. That way, if it throws something you didn't expect, it may either be something critical; something that should bubble up the call stack and possibly crash the application; or something you have not thought of.

For example, you may wish to handle IOExceptions thrown by I/O code so that you can relay the problem back to the user. However, the same operations may throw something more critical such as an AccessViolationException. In this case, you might want the program to terminate, or handle the problem in a different way.

Generic exception handling should only really be used in cases where you do not care what error occurred, and subsequently don't want it affecting the rest of your process.

Samuel Slade
  • 8,405
  • 6
  • 33
  • 55
2

The only potential cause for an exception that I see in your example is if list is null. OrderByDescending() should return an empty IEnumerable<> rather than a null reference.

If I read that correctly, it might make more sense to catch NullReferenceException:

try
{
...
} catch (NullReferenceException exception)
{
  MessageBox.Show(...);
}

However, this really depends on the needs of your application. If your intention is just to alert the user or to log all exceptions, catching the Exception class is fine. If you need special handling for different types of exceptions - such as sending an email alert instead of just logging the message - then it makes sense to use specific exception types:

try
{
} 
catch(NullReferenceException e)
{
//...
} 
catch(StackOverflowException e)
{
//...
}
catch(Exception e)
{
/// generic exception handler
}
3Dave
  • 28,657
  • 18
  • 88
  • 151
2

Which exception to use really depends on the code in the try block. In general you want to catch exceptions that you can do something with and let exceptions you have no power over move to high levels of your code where you can perform some action that makes since. One of the most common mistakes I see people make is attempting to catch errors that they have no ability to handle.

for example

Void ChoseFile()
{
     try
     { 
         string FileName = GetInputFile()
     }    
     catch( InvalidFileSelectedException ex)
     { 
         //In this case we have some application specific exception 
         //There may be a business logic failure we have some ability 
         //to infomr the user or do an action that makes sense  
     }
     catch(FileNotFoundException exfilenot found)
     { 
         //In this case we can do somthing different the the above 
     }
     catch(Exception ) 
     { 
         //Normal I would not use this case we have an error we don't know what to do 
         //with. We may not have a usefull action.  At best we can log this exception                               
         // and rethrow it to a higher level of the application that can inform the user
         // fail the attempted action.  Catching here would only suppress the failure.
      }

} 
rerun
  • 25,014
  • 6
  • 48
  • 78
1

Since you are dealing with a Dictionary.. then you want to look at these 2 exceptions

  • The key of keyValuePair is a null reference (Nothing in Visual Basic).

  • ArgumentException An element with the same key already exists in the Dictionary(TKey, TValue).

    KekValuePair Exception This is taken from the MSDN site

Random832
  • 37,415
  • 3
  • 44
  • 63
MethodMan
  • 18,625
  • 6
  • 34
  • 52
1

You should always catch exceptions with an as specific class as possible.

If you know what to do if a file is locked, but you regard all other errors as unexpected and impossible to handle, you should catch System.IO.IOException and deal with the error. You should only catch Exception (or just catch {) for gracefully exiting.

Anders Marzi Tornblad
  • 18,896
  • 9
  • 51
  • 66
0

Use the exception type that you might expect but still not be able to prevent and that you can adequately handle. Let anything else bubble up to somewhere that might expect it or can handle it.

In your case here, I might expect that I would run into a NullReferenceException if the dictionary is null. But I would not catch it. This is something I can validate against instead

if (dictionary != null) 

So there is no reason to allow an exception to even happen. Never use exceptions for control flow, and validate against known causes.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
0

Some classes/methods will throw different exceptions, depending on the error. For example, you might be using the File class to write data to a file. You could write multiple Catch statements for the exception types you could recover from, and a generic Exception catch to log and bubble up anything that can't be recovered from.

AndrewR
  • 6,668
  • 1
  • 24
  • 38
0

By using Exception you catch all exceptions. Of you use IOException or StackOverflowException you'll only catch errors of that type.

a StackOverflowException catched by a Exception still hold the same message, stack trace etc.

f2lollpll
  • 997
  • 6
  • 15
0

Exception handling philosophy I am sure you can find many other philosophies

Code defensively. Catching exceptions is more expensive than preventing the error in the first place.

Don't catch an exception and bury it by not handling it. You can spend many hours trying to find an error that has been suppressed.

Do log errors that you catch. This helps in analyzing the problem. You can check to see if more than one user is having the same problem I prefer a database for logging, but a flat file, or the event log are also suitable. The database solution is easiest to analyze but may introduce additional errors.

If the error is due to bad data entered by the user, inform the user of the problem and allow them to retry. Always allow an escape route if they cannot fix the problem.

Catch the error as close to the source as possible This could be a database procedure, a method in a data access layer (DAL) or some other location.

Handling the exception is different than catching it. You may need to rethrow the exception so that it can be handled higher up the stack or in the UI.

Rethrowing the exception can be done in at least two ways. throw by itself does not alter the stack. throw ex does alter or add to the stack with no benefit.

Sometimes it is best not to catch an exception, but rather let it bubble up.

If you are writing services (web or windows) that do not have a user interface (UI) then you should always log the error. Again, this is so that someone can analyze the log or database file to determine what is happening.

You always want someone to know that an error has occurred.

Having a lot of catch statements for a try block can make your code more difficult to maintain, especially if the logic in your catch blocks is complex. Instead, code defensively.

Remember that you can have try catch blocks within catch blocks.

Also, don't forget to use the finally block where appropriate. For example, closing database connections, or file handles, etc.

HTH Harv

Harv
  • 523
  • 3
  • 8