我对IDisposable接口和C#中的using关键字有一点混淆,我们可以在哪些类上使用它。
using (DataSet studentDS = GetMyStudentDS())
{
// here comes some code
}
我发现从DataSet类继承的类没有被垃圾收集器最终确定,如果是这样的话,最好将它放在using块中,以便在完成任务后手动完成。有人可以为了所有人的利益而简要介绍一下。感谢。
答案 0 :(得分:4)
我个人不会将它用于DataSet
。当我需要关闭连接并处理它时,我会使用using
语句,例如文件阅读器,数据库或SharePoint连接。 C#是一种托管语言,CLR将为您处理垃圾收集,在使用DataSet的情况下,我仍然会遵循这一原则(让CLR为您完成)。
http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx
答案 1 :(得分:3)
将它放在使用块
中是一个好习惯
是的。由于DataSet实现了IDisposible接口。 DataSet扩展了MarshalByValueComponent类。 MarshalByValueComponent类实现了IDisposable。
任何派生类型也将实现IDisposable。如果它没有显式实现(换句话说覆盖IDisposable.Dispose),将调用基本方法(DataSet.Dispose)。
关于Finalizer,这是一个单独的概念,即使开发人员无法调用Dispose方法(或忘记使用阻止),也要确保清理非托管资源。
答案 2 :(得分:2)
终结器(析构函数)和IDisposable模式之间存在差异。 GC在非确定性时间调用终结器,用于清除与类关联的非托管资源并释放实例占用的内存。析构函数运行时,它无法控制。
IDisposable用于在确定的时间清理对象。它不会释放对象占用的内存,但它通常用于关闭文件,数据库连接......
因此,一般规则是,如果一个对象实现了IDisposable,最好将其实例包装在using
关键字中,以便尽快释放资源。
答案 3 :(得分:0)
DataSet实现了IDisposable
,但是他们压制了他们的终结
所以它真的不需要,它们不会引入任何非托管代码
不要用using
语句包装它,但不要忘记在sql连接或数据读取器周围使用using
关键字。
答案 4 :(得分:0)
C#允许您对实现using
的所有内容使用IDisposable
。为什么?因为使用只是一种语法糖。 using(obj){/*somecode*/}
实际上是这样的:
try
{
/*somecode*/
}
finally
{
if(obj!=null) obj.Dispose();
}
如果您使用的是键入的DataSet
您可能已经注意到自动生成的类不会覆盖Dispose(bool)
。因此Dispose
对您自动生成的表和列没有任何作用。
为了帮助您的数据设置可用内存(并且它确实存在问题),请在自动生成的TypedDataSet(部分文件)中覆盖Dispose(bool)
。做这样的事情:
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
会有意义。
答案 5 :(得分:-1)
是的,绝对可以使用任何对象初始化代码 块。使用它没有任何副作用。在任何情况下,如果 你想100%确定一个对象的垃圾收集保持它 在使用块。