using语句的记忆碎片
资源的清理using语句的用法前言
垃圾回收是‘运行时’的一个重要的职责。但是,垃圾回收的宗旨是提高内存的利用。它不是用来清理文件的句柄、数据库链接字符串、端口或者其他有限资源的。
一、终结器的用途
终结器允许程序员编写代码来清理一个类的资源。但是,终结器不能从代码中显示的调用,而是由垃圾回收器负责对一个对象实例调用终结器。因此,开发者不能在编译时确定执行终结器的时间,唯一能确定的是终结器会在上次使用这个对象后,并在应用程序结束之前的某个时刻运行。
终结器的定义:public class TemporaryFileStream1
{
~TemporaryFileStream1()
{
Close();
}
public FileStream Stream { get; set; }
public FileInfo File { get; set; }
public void Close()
{
if (Stream != null)
{
Stream.Close();
}
if (File != null)
{
File.Delete();
}
}
}终结器没有参数,所以终结器不能重载。终结器只能被垃圾回收器调用,因此为终结器添加修饰符没有任何的意义,并且终结器也不允许添加访问修饰符。基类的终结器会作为对象的终结器的一部分被调用。终结器主要负责释放像数据库连接和文件句柄这样的资源,这样的资源需要通过显示的行动来进行清理,而垃圾回收器是作为一个对资源清理的一个备用机制。假如使用某一个类开发者忘记显示调用必要的代码,就可以依赖垃圾回收器去调用终结器来清理资源,所以说假如我们自己做好显示调用方法来清理资源,那几乎用不到终结器来不确定的释放资源。由于确定性终结的重要性,基类库为这个使用模式包含了一个特殊的接口,而且c#已将这个模式集成到语言中来了。IDisposable接口用一个名为Dispose方法来定义这个模式的细节。
使用IDisposable清理资源:
public class TemporaryFileStream2 : IDisposable
{
~TemporaryFileStream2()
{
Close();
}
public FileStream Stream { get; set; }
public FileInfo File { get; set; }
public void Close()
{
if (Stream != null)
{
Stream.Close();
}
if (File != null)
{
File.Delete();
}
}
//IDisposable定义的方法在基类中的实现
public void Dispose()
{
Close();
}
}class Progrom
{
static void Search1()
{
TemporaryFileStream2 fileStream = new TemporaryFileStream2();
//......
//......
fileStream.Dispose();
//......
//......
}
}无论实现还是调用IDisposable接口,步骤都是十分的简单,然而还要记住一点:在实例化之后并在调用Dispose方法之前有可能出现一个异常,就不会调用显示的资源的清理的方法。为了避免这个情况,调用者需要实现一个try/finally块。但是,开发者可以不需要写一个这样的块。可以用using语句来实现这个功能。
执行using语句class Progrom
{
static void Search2()
{
using (TemporaryFileStream2 fileStream1 = new TemporaryFileStream2(), fileStream2 = new TemporaryFileStream2())
{
//......
//......
}
}
}上面的功能与写一个显示的try finally是一样的,总之using语句只是提供一个语法的捷径。在using语句中,可以实例化多个变量,只需用逗号分隔每一个变量。这里的关键在于,所有的变量都是具有相同的类型,而且都是实现了IDisposable。这一点要切记。