What's the point of nested try-catch block?
Here's a pseudo-code:
try
{
TextReader tr = new StreamReader("filename");
try
{
string content = tr.ReadToEnd();
}
catch(Ex开发者_JS百科ception ex)
{ /*Show error message*/ }
finally
{ tr.Close();}
}
catch(Exception ex)
{ /*Show error message*/ }
Ok, that code is a sample of a book. What i don't understand is why a nested try-catch block is used.
If
string content = tr.ReadToEnd();
goes wrong then outer catch should catch the exception right? So I can't see any point of using extra try-catch for that line!
If you see any misconceptions here then I'd be glad if you could point them out!
Also are there any cases where nested try-catch would be reasonable to use?
Differences between your example and similar code in which there is only one, outer, catch:
1) If the inner block throws, then the message is printed before calling Close()
. This might be significant if Close()
also contains logging.
2) If an inner exception is thrown and caught, and then in the finally block Close()
also throws, you get two exceptions and you handle two exceptions. With only one catch block, if Close()
throws then what happens next might depend on language, but you won't get two error messages printed. I'd expect the second exception to replace the first one, but I don't swear that's what happens in all languages with finally
, or even all languages I've used...
3) //Show error message
is just a comment, it does nothing. It may be the intention of the author that you'd show a different error message in the two different cases. The inner one would say, "read failed", and the outer one would say, "cannot open file". Or something like that. To achieve that with only one catch block, you could set and check a flag indicating progress (which probably doesn't make the code any simpler than two catch blocks), or you could rely on the exception itself to contain the appropriate error message (in which case good luck with integrating your localization framework with exception-throwing functions in built-in or third-party libraries).
Note that even if you only have one catch, you still need two tries because of the finally
. This is no good:
try {
TextReader tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
tr.Close();
}
Because by the looks of this language, tr
will not be in scope in the finally
block, so we can't close it there. We have to close it inside the block that deals with creating it. It may be that we could deal with it like this:
TextReader tr = null;
try {
tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
if (tr != null) {
tr.Close();
}
}
But that doesn't really simplify things much compared with the original code, we still have differences 2-3 to contend with, and now we don't handle exceptions from Close()
at all. So for many purposes the original code with multiple try/catch was better.
if
string content = tr.ReadToEnd();
goes wrong then outer catch should catch the exception right?
No, the inner catch
will catch it and display the error message. Then the inner finally
is executed. Then the outer try
block finishes without any exceptions to handle, because the inner try-catch
block has already dealt with it.
One example I use for is when I need to handle a specific type of exception:
try
{
//...
//IMPORTANT CODE HERE
//....
try
{
// Read in non-existent file.
using (StreamReader reader = new StreamReader("not-there.txt"))
{
reader.ReadToEnd();
}
}
catch (FileNotFoundException ex)
{
//Do something important here
}
//...
//MORE IMPORTANT CODE
//...
}
catch(Exception ex) ///An Exception I'm not expecting
{ //oops...handle gracefully here
}
You want to catch the exception as early as possible. It is bad practice to let things bubble to the outer exception. Remember the rule: Fail early, Fail often.
精彩评论