如何:使用 finally 执行清理代码(C# 编程指南)
finally 语句的目的是确保即使在引发异常的情况下也能立即进行必要的对象(通常是保存外部资源的对象)清理。 此类清理功能的一个示例是在使用后立即对 FileStream 调用 Close,而不是等待公共语言运行时对该对象进行垃圾回收,如下所示:
static void CodeWithoutCleanup()
{
System.IO.FileStream file = null;
System.IO.FileInfo fileInfo = new System.IO.FileInfo("C:\\file.txt");
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
file.Close();
}
示例
为了将上面的代码转换为 try-catch-finally 语句,需要将清理代码与工作代码分开,如下所示。
static void CodeWithCleanup()
{
System.IO.FileStream file = null;
System.IO.FileInfo fileInfo = null;
try
{
fileInfo = new System.IO.FileInfo("C:\\file.txt");
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
catch(System.UnauthorizedAccessException e)
{
System.Console.WriteLine(e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
}
因为在 OpenWrite() 调用前,try 块内随时都有可能发生异常,OpenWrite() 调用本身也有可能失败,所以我们无法保证该文件在我们尝试关闭它时处于打开状态。 finally 块添加了一项检查,以确保在调用 Close 方法前,FileStream 对象不为 null。 如果没有 null 检查,finally 块可能引发自身的 NullReferenceException,但是应当尽可能避免在 finally 块中引发异常。
在 finally 块中关闭数据库连接是另一个不错的选择。 因为有时候数据库服务器允许的连接数是有限的,所以应尽快关闭数据库连接。 在由于引发了异常而无法关闭连接的情况下,使用 finally 块也是比等待垃圾回收更好的一种选择。