views:

221

answers:

9
A: 

You could also return in the catch block, so there is that 4th option. Return false, return null, etc... (even return a default value.)

Letting the catch block fall through implies that you have successfully dealt with the Exception that was raised in your try block. If you haven't, better rethrow, or fail in some other way.

Zak
At an IL level that's the same as letting it fall out of the bottom of the catch block. You have handled the exception, so execution continues.
Greg Beech
+7  A: 

Well, here are those different options in code:

Option 1: Rethrow

try
{
    // Something
}
catch (IOException e)
{
    // Do some logging first
    throw;
}

Option 2: Throw a different exception

try
{
    // Something
}
catch (IOException e)
{
    // Do some logging first
    throw new SorryDaveICantDoThatException("Oops", e);
}

Option 3: Let the thread fall out of the bottom

try
{
    // Something
}
catch (IOException e)
{
    // Possibly do some logging, and handle the problem.
    // No need to throw, I've handled it
}

EDIT: To answer the extra question, yes - if you need to handle a rethrown exception, that needs to be handled in an outer scope, exactly as shown in the question. That's very rarely a good idea though. Indeed, catch blocks should relatively rare in the first place, and nested ones even more so.

Jon Skeet
Shouldn't that last `catch` block contain "Do some **cleanup** first"?
Joren
@Joren: Cleanup would usually be in a finally block, not a catch block.
Jon Skeet
Jon Skeet,are you the one written C# in Depth ?
@isystemize: Yup. If you've got it, I hope you're finding it useful.
Jon Skeet
Catch blocks in an enclosing try block will catch the newly-thrown/rethrown exception, but subsequent catch blocks associated with the same try block won't.
Jon Skeet
Jon I have updated one more doubt,request you to read my update and clarify my doubt.
Thanks Jon now things are clear
Jon, you're right, but `finally` is a different kind of cleanup from what I meant. (Maybe I should've used another term.) My point was that logging in almost all cases doesn't constitute handling an exception, that's just swallowing it. If there is some useful handling you could do, then you should do it. If not, then you shouldn't catch the exception at all.
Joren
Okay, I'll change the comment.
Jon Skeet
+1  A: 

1) Re-throw

try
{
    ...
}
catch (Exception e)
{
    ...
    throw;
}

2) Throw a new exception

try
{
    ...
}
catch (Exception e)
{
    ...
    throw new NewException("new exception", e);
}

3) Fall out

try
{
    ...
}
catch (Exception e)
{
    ...
}
Taylor Leese
NOTE: your re-throw example is incorrect. It should just throw; otherwise call stack is lost.
Mitch Wheat
Interesting. I didn't know that. Edited and updated.
Taylor Leese
+2  A: 

These are the choices. Difference between 1 and 2 is that if an exception is thrown and you want to debug to the position is it thrown, you will get there with option 1 (all the way down in the try block at the specific object). With option 2 you will and up only at that line (throw new Exception2())

3 is when you want to ignore the exception and just continue

//1
catch (Exception ex)
{
    throw;
}

//2
catch (Exception ex)
{
    throw new Exception2();
}

//3
catch (Exception ex)
{
}
return something;
PoweRoy
Option 2 is usually bad idea, you want to pass the caught exception as innerException to the new exception your're throwing, in case the caller in interested in details of what caused the exception.
Dan C.
true, but this was just a demo ;)
PoweRoy
A: 

this isn't c# specific, it's true of any programming language (call them exceptions, call them errors, call them whatever you want).

So, the answer to you question is that this is a basic premise of all programming and you must determine the correct action to take in your code, given the error, the circumstance and the requirements.

KevinDTimm
+1  A: 

rethrow the same exception:

try
{
    // do something that raises an exception
}
catch (SomeException ex)
{
    // do something with ex
    throw;
}

throw a different exception

try
{
    // do something that raises an exception
}
catch (SomeException ex)
{
    // do something with ex
    throw new SomeOtherException(ex);  // NOTE: please keep ex as an inner exception
}

let the thread fall out:

try
{
    // do something that raises an exception
}
catch (SomeException ex)
{
    // do something with ex
}
// the code will finish handling the exception and continue on here
rein
When rethrowing the exception it's generally better to use 'throw;' or you lose the stack trace before that point. Unless that's what you want, of course.
Pike65
You're correct. I have no idea why I typed that since I've argued the same point multiple times today already. Thanks.
rein
+2  A: 

In most production systems the last thing you want is a truly unhandled exception. This is why you typically try and catch statements.

You might be wondering why you would want to throw an error you've caught, and here are a few real world examples.

  1. You've caught an exception in a WCF Application, logged the exception, then thrown a faultException instead to be returned to the WCF client. In the same way you might have a traditional asmx, caught an exception, then thrown a SOAP exception back to the client. Point is certain exceptions need to abide by certain rules: a standard .net exception would not be digested well by a WCF client for example.

  2. You've caught an exception somewhere deep inside your code, logged the exception and possibly even taken some action. But higher up in your code you have another routine that is also waiting for exceptions, at this point higher up, an exception could easily change the business workflow. By catching the exception lower down, the code higher up is not aware of any exception, so you need to throw the exception back out to be caught higher up, so that the code you wrote up there can adjust the workflow. Ofc none of this happens by magic, it all has to be coded, and differant programmers use differant techniques.

  3. You might also want to catch an exception around just 1 or a few statements, for example getting a configuration value from an XML file, if something goes wrong, .net might just return object reference not set. You might catch this, then rethrow the exception as "Configuration Value : Customer Name not provided".

Hope this helps.

JL
definitely very helpful
productive or production?
Mitch Wheat
I would say that in a production system the last thing you want is data which was screwed up due to the system trying to continue with a request (or whatever) even when it had seen that things were wrong. That's why try/catch blocks should be rare.
Jon Skeet
@Jon Skeet - hence the practice on trying.... catching... logging... throwing is becoming popular. And you're right, if you're not very careful you'll end up in the poop quickly, especially if you're iterating or working with a collection.
JL
A: 

Taylor,

As you are learning about Exception handling I would like to add my 2 cents. Exception throwing is very expensive ( expensive being memory hogging of course ) so in this case you should consider assigning the error message to a string and carry it forward through the application to the log or something.

for example:

string errorMessage = string.empty;

try
{
...
}
catch(Exception e)
{
   errorMessage = e.Message + e.StackTrace;;
}

This way you can carry this string anyway. This string can be a global property and can be emailed or logged in text file.

Ved
A: 

I think that there is something to add to the great answers we've already got here.

It may be part of your overall architectural design (or not) but what I've always observed is that you typically only catch where you can add value (or recover from the error) - in other words, not to try...catch...re-throw multiple times for a single operation.

You should normally plan a consistent pattern or design for how you handle exceptions as part of your overall design. You should always plan to handle exceptions in any case, unhandled exceptions are ugly!

RobS