这是伪代码:
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*/ }
好的,该代码是一本书的样本。我不明白的是为什么使用嵌套的try-catch块。
如果
string content = tr.ReadToEnd();
出错然后外部捕获应该捕获异常吗?所以我看不出为该行使用额外的try-catch的任何意义!
如果你在这里看到任何误解,那么如果你能指出它们我会很高兴的!
还有什么情况可以使用嵌套的try-catch吗?
答案 0 :(得分:3)
示例和类似代码之间的差异,其中只有一个,outer,catch:
1)如果内部块抛出,则在调用Close()
之前打印消息。如果Close()
还包含日志记录,则这可能很重要。
2)如果抛出并捕获内部异常,然后在finally块Close()
中抛出,则会出现两个异常并处理两个异常。只有一个catch块,如果Close()
抛出,那么接下来发生的事情可能取决于语言,但是不会打印出两条错误消息。我希望第二个例外可以取代第一个例外,但我不会发誓,finally
所有语言都会发生这种情况,甚至我用过的所有语言......
3)//Show error message
只是一个评论,它什么都不做。作者可能会在两种不同的情况下显示不同的错误消息。内在的人会说,“读取失败”,外部人会说,“无法打开文件”。或类似的东西。要实现只有一个catch块,您可以设置并检查指示进度的标志(这可能不会使代码比两个catch块更简单),或者您可以依赖异常本身来包含相应的错误消息(在这种情况下,将您的本地化框架与内置或第三方库中的异常抛出函数集成在一起可以带来好运。)
请注意,即使您只有一个捕获,但由于finally
,您仍需要两次尝试。这不好:
try {
TextReader tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
tr.Close();
}
因为根据这种语言的外观,tr
块不在finally
块的范围内,因此我们无法将其关闭。我们必须关闭里面处理创建它的块。可能我们可以像这样处理它:
TextReader tr = null;
try {
tr = new StreamReader("filename");
string content = tr.ReadToEnd();
} catch(Exception ex) {
// show error message
} finally {
if (tr != null) {
tr.Close();
}
}
但与原始代码相比,这并没有真正简化事情,我们仍然存在差异2-3来应对,现在我们根本不处理来自Close()
的异常。因此,出于多种目的,具有多个try / catch的原始代码更好。
答案 1 :(得分:2)
如果
string content = tr.ReadToEnd();
出错,那么外部捕获应该捕获异常吗?
不,内部catch
将捕获它并显示错误消息。然后执行内部finally
。然后外部try
块完成,没有任何异常处理,因为内部try-catch
块已经处理过它。
答案 2 :(得分:2)
我使用的一个例子是当我需要处理特定类型的异常时:
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
}
答案 3 :(得分:1)
您希望尽早捕获异常。让事情冒泡到外部异常是不好的做法。记住规则:早退,经常失败。