简体   繁体   中英

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(Exception 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM