问题:
当一个对象的工作完成或者超出作用域时,你需要采用一种方式确保一些处理得到执行。
解决方案:
使用using 语句,代码如下所示。
using System;
using System.IO;
// ...
using (FileStream FS = new FileStream("Test.txt", FileMode.Create))
{
FS.WriteByte((byte)1);
FS.WriteByte((byte)2);
FS.WriteByte((byte)3);
using (StreamWriter SW = new StreamWriter(FS))
{
SW.WriteLine("some text.");
}
}
讨论:
using 语句非常易于使用,并且可以避免编写多余代码的麻烦。如果解决方案中没有使用using 语句,将会如下所示。
FileStream FS = new FileStream("Test.txt", FileMode.Create);
try
{
FS.WriteByte((byte)1);
FS.WriteByte((byte)2);
FS.WriteByte((byte)3);
StreamWriter SW = new StreamWriter(FS);
try
{
SW.WriteLine("some text.");
}
finally
{
if (SW != null)
{
((IDisposable)SW).Dispose();
}
}
}
finally
{
if (FS != null)
{
((IDisposable)FS).Dispose();
}
}
关于using 语句,需要注意以下几点。
存在一个using 指令,如下所示。应将其与using 语句区分开。这可能会使初次接触这一语言的开发人员混淆。
using System.IO;
using 语句的子句中定义的变量都必须具有相同的类型,并且必须具有一个初始化器。不过,因为可以在单个代码块前使用多个using 语句,所以这并不是一个重大的限制。
using 子句中定义的变量在using 语句体中被认为是只读的。这可以阻止开发人员在尝试处置变量最初引用的对象时无意中将变量转变成引用不同的对象,避免引发问题。
不应该在using 块外声明变量,然后在using 子句内初始化它。
下面的代码说明了最后一点。
FileStream FS;
using (FS = new FileStream("Test.txt", FileMode.Create))
{
FS.WriteByte((byte)1);
FS.WriteByte((byte)2);
FS.WriteByte((byte)3);
using (StreamWriter SW = new StreamWriter(FS))
{
SW.WriteLine("some text.");
}
}
对于这段示例代码来说,不会有任何问题。但是,要考虑到变量FS 是可以在using 块外使用的。实际上,可以将这段代码修改为下面这样。
FileStream FS;
using (FS = new FileStream("Test.txt", FileMode.Create))
{
FS.WriteByte((byte)1);
FS.WriteByte((byte)2);
FS.WriteByte((byte)3);
using (StreamWriter SW = new StreamWriter(FS))
{
SW.WriteLine("some text.");
}
}
FS.WriteByte((byte)4);
这段代码可以编译,但会在这个代码段的***一行上引发一个ObjectDisposedException,因为已经对FS 对象调用了Dispose 方法。对象此时还没有被垃圾回收,仍然以被处置过的状态存在于内存中。
参考:
MSDN 文档中的“Cleaning Up Unmanaged Resources”“IDisposable 接口”“Using foreachwith Collections”和“实现Finalize 和Dispose 以清理非托管资源”主题。