6.5
使用finally块
要记住的一个重点是:当一个异常抛出时,它会改变程序的执行流程。这意味着你不能保证当一个语句结束之后,它后面的一个语句肯定会运行,因为前一个语句可能抛出一个异常。仔细看下面这个例子,很容易误认为对reader.close的调用是肯定会发生的,毕竟,它就是包含在代码中的:
Text.Reader reade= src.OpenText();
String line;
While((line=reader.ReadLine())!=null)
{
Source.Text+=line+”\n”;
}
Reader.Close();
有的时候,如果一个特定的语句不运行是不会造成问题的。但在许多情况下,它都会造成大问题。假如一个语句的作用是释放它之前的一个语句获取的资源,那么假如执行这个语句失败,就会造成资源得不到释放。上例清楚地展示了这一点:如果对src.OpenText的调用成功,它会获取一个资源(一个文件handle或者说文件句柄),而你必须确保调用reader.Close来释放该资源。否则,迟早会用光所有的文件handle,造成无法打开任何更多的文件(如果你觉得文件handle过于普通,不妨把它换成数据库连接来重新想一想)。
为了确保一个语句总是运行(不管是否抛出一个异常),需要将该语句放到一个finally块中。fially块要么紧接在try块之后,要么紧接在try块之后的最后一个catch处理程序之后。只要程进入与一个finally块关联的try块,则finally块始终都会运行——即使发生了个异常。如果一个异常被抛出,而且在本地被捕捉到,那么将首先运行异常处理程序,然后运行finalIy块。如果异常没有在本地捕捉到(runtime必须搜索调用方法列表来找到一个匹配的处理程序).那么将首先运行finally块。在任何情况下,finally块总是运行。
为了确保reader.Close总是得到调用,可以采用下面这个方案
TextReader reader=nu;;
Try
{
reade= src.OpenText();
String line;
While((line=reader.ReadLine())!=null)
{
Source.Text+=line+”\n”;
}
}
Finally
{
If(reader!=null)
{
Reader.Close();
}
}
这样一来,即使抛出了一个异常,finally块也能保证reader.Close语句总是得以执行。第l4章将介绍解决同一个问题的另一个方案。
●如果希望继续学习下一章的学习,请继续运行Visual Studi0 2008.然后阅读第7章。
●如果希望现在就退出Visual Studi0 2008,请选择“文件”|“退出”。如果看到“保存”对话框,请单击“是”按钮(如果使用的是Visual Studi0 2008)或“保存”按钮(如果使用的是Visual Studio 2008速成版),从而保存项目。
目标 |
操作 |
抛出个异常 |
使用一个throw语句。例如:
throw new FormatException(source); |
确保整数运算总是进行溢出检查 |
使用check关键字。例如:
int number=int.MaxValue;
checked
{
number++;
} |
捕捉个特定的异常 |
写一个catch处理程序来捕捉特定的异常类。例如:
try
{
...
}
catch(FormatException fEx)
{
...
} |
用一个catch处理程序来捕捉所有异常 |
写一个catch处理程序来捕捉特定的异常类。例如:
try
{
...
}
catch(Exception ex)
{
...
} |
确保特定的代码总是运行,即使前向抛出了异常 |
将代码入到一个finally块中,例如:
try
{
...
}
finally
{
//总是运行
} |