在C#中,我对IDisposable接口和using关键字有些困惑,不知道哪些类可以使用它们。
using (DataSet studentDS = GetMyStudentDS())
{
// here comes some code
}
我发现继承自DataSet类的类不会被垃圾回收器终止,如果这样的话,将其放入using块中以便在完成任务后手动完成是否是一种好的做法。有人能为大家简要说明一下吗?谢谢。
在C#中,我对IDisposable接口和using关键字有些困惑,不知道哪些类可以使用它们。
using (DataSet studentDS = GetMyStudentDS())
{
// here comes some code
}
我发现继承自DataSet类的类不会被垃圾回收器终止,如果这样的话,将其放入using块中以便在完成任务后手动完成是否是一种好的做法。有人能为大家简要说明一下吗?谢谢。
把它放在using块中是一个好的做法吗?
是的。因为DataSet实现了IDisposible接口。DataSet扩展了MarshalByValueComponent类。MarshalByValueComponent类实现了IDisposable。
任何派生类型也将实现IDisposable。如果它没有显式实现(换句话说,覆盖IDisposable.Dispose),那么将调用基方法(DataSet.Dispose)。
关于Finalizer,这是一个单独的概念,以确保即使开发人员未调用Dispose方法(或忘记使用块),也会清理非托管资源。
个人而言,我不会将其用于DataSet
。当我需要关闭连接和处理它时,例如文件阅读器、数据库或SharePoint连接,我会使用using
语句。C#是一种托管语言,CLR会为您处理垃圾回收,在使用DataSet的情况下,我仍然会坚持这个原则(让CLR为您完成)。
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
析构函数和IDisposable模式是有区别的。析构函数在非确定性时间由GC调用,用于清理与类相关的非托管资源并释放实例占用的内存。析构函数运行的时间是无法控制的。
IDisposable用于在确定性时间清理对象。它不会释放对象占用的内存,但通常用于关闭文件、数据库连接等操作。
因此,一般规则是,如果一个对象实现了IDisposable接口,最好使用using
关键字包装其实例,以便尽快释放资源。
DataSets 实现了 IDisposable
接口,但是它们抑制了其终结器。
因此,实际上不需要使用终结器,因为它们不会引入任何非托管代码。
不要使用 using
语句包装它,但是在使用 SQL 连接或数据读取器时不要忘记使用 using
关键字。
C# 允许您在实现 IDisposable
的所有内容上使用 using
。为什么?因为 using 只是一种语法糖。 using(obj){/*somecode*/}
实际上就像这样:
try
{
/*somecode*/
}
finally
{
if(obj!=null) obj.Dispose();
}
protected override void Dispose(bool disposing)
{
foreach (DataTable tab in this.Tables)
{
if (tab != null)
{
tab.Clear();
tab.Columns.Clear();
tab.Dispose();
}
}
this.Tables.Clear();
base.Dispose(disposing);
}
现在在这个 SataSet
上使用 using
将会很有意义。
Dispose
(这就是using
语句所做的)并不会导致对象被垃圾回收。 - Jon Skeet