Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Exception handling concepts 1

Status
Not open for further replies.

GoTerps88

Programmer
Apr 30, 2007
174
US
There seems to be a difference in viewpoint on how to handle exceptions, so I thought it would be interesting to garner feedback from others on this.

I think it's fair to say that you should handle exceptions at the calling method rather than at the class level but maybe I am wrong. I was also led to believe we should throw exceptions from the class method back to the caller, and then let the caller handle the exception, display error message etc.

Then, I read an article by Anders Hejlsberg, who seemed to offer another method of handling exceptions. He said that one should have 10 try/catch blocks per throw. Since he is the one who created the C# language, it might be good to listen to his advice. I think I read something that throwing exceptions is an expensive operation. I could be wrong and I can't seem to find the article he wrote this in.

Code:
public static void updEmployee()
{
     try
     {
     //code for updating an employee in the database
     objCmd.ExecuteNonQuery();
     }
     catch(SQLException ex)
     {
         throw(ex);
     }
     catch(Exception ex)
     {
         throw(ex);     }
     finally
     {
        //dispose of objects
     }
}

So if we follow that advice, should we then turn this class method into this?

Code:
public static void updEmployee(int empID)
{
     //code for updating an employee in the database
     objCmd.ExecuteNonQuery();
}
And the client handles the exception like this?
Code:
protected void btn_Click(object sender, EventArgs e)
{
    try
     {
     //code for updating an employee in the database
     updEmployee(3333);
     }
     catch(SQLException ex)
     {
        
        lblMessage.Text = ex.Message;

     }
     catch(Exception ex)
     {
        
        lblMessage.Text = ex.Message;

     }
     finally
     {
        //dispose of objects
     }
}
 
ultimately it comes down to what your needs are. i have read a few different view points on the subject as well.
some of the concepts which i try to follow are:

1. only catch exceptions you expect. don't catch everything just because it might error.
good
Code:
try { return int.Parse(value); }
catch(FormatException e) { return 0; }
bad (potentially)
Code:
try { DoSomethingHere(); }
catch(Exception e) { }

if you catch an error, you should wrap and rethrow (not just swallow)
good
Code:
try { DoSomething(); }
catch (FileIOException e) { throw new DoSomethingException(e); }
bad
Code:
try { DoSomething(); }
catch(FileIOException e) { }

don't catch all exceptions
good
Code:
try { DoSomething(); }
catch (FileIOException e) { throw new DoSomethingException(e); }
bad
Code:
try{DoSomething();}
catch (Exception e) { new DoSomethingException(e); }

include a global exception handler so unhandled exceptions are at least logged.
Code:
AppDomain.UnhandledException += MyLastResourt;

private static void MyLastResourt(object sender, UnhandeledEventArgs e)
{
   //log error.
}

again these are guidelines and your specific needs my be different.

in my current project I loop through a list of objects and preform a complex operation on each. the process cannot stop if 1 oject fails. so within my foreach I catch the exception, log it and move on.
Code:
foreach(object myobject in mylistofobjects)
{
  try { RunProcessOn(myobject); }
  catch(Exception e) { Logger.Log(e); }
}

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
The rule of thumb I've seen is that you should only catch exceptions where you're able to do something with them.

I take that to mean that you should have catch statements at the UI to prevent the user from seeing an unhandled exception, as well as at any significant layer boundary within your code.

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
I tend to let an exception go as far as it can before I catch it. This way I'm going to be more informed if there's a problem. I usually let the caller catch the exception and then LOG THE EXCEPTION. When you write to your log, include the stacktrace. This will tell you the path your exception took and give you more info.

There's nothing more frustrating then going into some code and searching for hours simply to find

try
{
}
catch (Exception ex)
{
Console.WriteLine("duh... something happened...");
}

The only time I break this concept is if I'm going to cause a layer to fail such as the UI. I would rather have my user see "An error occured - please see the details below" instead of having the app crash "nicely".

 
Thanks for the response. What I was really trying to get at is how to handle the exceptions when you have several nested method calls. One method calls a method, which then calls another method. Is it really useful to catch exceptions at each method call? With Java, you are really forced to catch exceptions in this manner or the compiler will throw an error.
 
I tend to try and throw as many exceptions as possible and catch only those I can do something with, regardless of how many levels deep you go. This way, each object/method protects itself and leaves the calling client to work out how to deal with problems.

Code:
// Throwing exceptions
public bool Login(string username, string password)
{
  if(username == string.empty)
  {
    throw new MyCustomLoginCredentialException("Username is requried");
  }
  if(password == string.empty)
  {
    throw new MyCustomLoginCredentialException("Password is requried");
  }

  //login logic goes here...
  if(login failed)
  {
    throw new MyCustomLoginFailedException();
  }
}

Then in the calling code you only catch those exceptions you can do something with:

Code:
protected btnClick(object sender, EventArgs e)
{
  try
  {
    Login(txtUsername.Text, txtPassword.Text)
  }
  catch (MyCustomLoginCredentialException ex)
  {
    lblMessage.Text = "Missing login credentials - " + ex.Message;
  }
  catch (MyCustomLoginFailedException ex)
  {
    lblMessage.Text = "Invalid login credentials, please try again.";
  }
  catch (Exception ex)
  {
    lblMessage.Text = "Unexpected error - " + ex.Message;
  }
}

This approach may not suit everyone and can be quite time consuming.

HTH

Smeat
 
I found the article by Hejlsberg I referred to earlier in the post.


Perhaps someone can provide clarity on his meaning regarding throwing or not throwing exceptions.

Anders Hejlsberg: It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch. Or in C#, using statements, which are like try finally.
 
Interesting interview.
However: mr. H. is not arguing that 'one should have 10 try/catch blocks per throw' as you stated in your first post. Actually the interview is about why C# does not have 'checked exceptions'. Mr H. reasons that having checked exceptions 'requires you to either catch declared exceptions or put them in your own throws clause.', and he states that 'in any kind of event-driven application like any kind of modern UI, you typically put an exception handler around your main message pump, and you just handle exceptions as they fall out that way.'. i.e. definitly not in every calling method.
However, you may still have to clean-up some resources, so: 'In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch. Or in C#, using statements, which are like try finally.'

All in all the idea seems to be that the calling code could clean-up early, and catch / handle exception late.
Which of course does not mean that the executing code can just throw around any exception; I think that in that respect the example by Smeat is very clear.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top