我对 IDisposable 接口和 C# 中的 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
. using
当我需要关闭连接并处理它时,我会使用语句,例如文件阅读器、数据库或 SharePoint 连接。C# 是一种托管语言,CLR 将为您处理垃圾收集,在使用 DataSet 等情况下,我仍然会坚持这一原则(让 CLR 为您完成)。
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
终结器(析构函数)和 IDisposable 模式之间存在区别。GC 在不确定的时间调用终结器,用于清理与类关联的非托管资源并释放实例占用的内存。当析构函数运行时,它是你无法控制的。
IDisposable 用于在确定的时间清理对象。它不会释放对象占用的内存,但通常用于关闭文件、数据库连接……
所以一般规则是,如果一个对象实现了 IDisposable,最好将其实例包装在using
关键字中,以便尽快释放资源。
DataSet 实现IDisposable
了 ,但它们抑制了它们的终结。
所以真的不需要,他们没有引入任何非托管代码。
不要用using
语句包装它,但是不要忘记using
在 sql 连接或数据读取器周围使用关键字。
C# 允许您using
在所有实现IDisposable
. 为什么?因为 using 只是一种语法糖。using(obj){/*somecode*/}
实际上是这样的:
try
{
/*somecode*/
}
finally
{
if(obj!=null) obj.Dispose();
}
如果您使用的是 TypedDataSet
您可能已经注意到您的自动生成的类不会覆盖Dispose(bool)
。因此Dispose
,对您的自动生成的表和列没有任何作用。为了帮助您的数据集释放内存(它确实有问题)覆盖Dispose(bool)
在您的自动生成的 TypedDataSet(在部分文件中)。做这样的事情:
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);
}
现在使用using
它SataSet
会很有意义。
是的,绝对可以在 using 块中使用任何对象初始化代码。使用它没有副作用。在任何情况下,如果您想 100% 确定对象的垃圾收集,请将其保留在 using 块中。