3

我对 IDisposable 接口和 C# 中的 using 关键字有点困惑,我们可以在哪些类上使用它。

using (DataSet studentDS = GetMyStudentDS())
{
    // here comes some code
}

我发现垃圾收集器没有最终确定从 DataSet 类继承的类,如果是这样,将其放在 using 块中以便在其工作完成后手动完成是一个好习惯。为了所有人的利益,有人可以简要介绍一下。谢谢。

4

6 回答 6

4

把它放在 using 块中是一个好习惯吗

是的。作为DataSet实现 IDisposible 接口。DataSet 扩展了 MarshalByValueComponent类。MarshalByValueComponent类实现 IDisposable。

任何派生类型也将实现 IDisposable。如果它没有显式实现(换句话说,重写 IDisposable.Dispose),则将调用基方法 (DataSet.Dispose)。

关于Finalizer,这是一个单独的概念,用于确保即使开发人员未能调用 Dispose 方法(或忘记使用块)也能清理非托管资源。

于 2012-05-29T07:21:39.293 回答
4

我个人不会将它用于DataSet. using当我需要关闭连接并处理它时,我会使用语句,例如文件阅读器、数据库或 SharePoint 连接。C# 是一种托管语言,CLR 将为您处理垃圾收集,在使用 DataSet 等情况下,我仍然会坚持这一原则(让 CLR 为您完成)。

http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

http://www.w3enterprises.com/articles/using.aspx

于 2012-05-29T07:22:05.110 回答
2

终结器(析构函数)和 IDisposable 模式之间存在区别。GC 在不确定的时间调用终结器,用于清理与类关联的非托管资源并释放实例占用的内存。当析构函数运行时,它是你无法控制的。

IDisposable 用于在确定的时间清理对象。它不会释放对象占用的内存,但通常用于关闭文件、数据库连接……

所以一般规则是,如果一个对象实现了 IDisposable,最好将其实例包装在using关键字中,以便尽快释放资源。

于 2012-05-29T07:20:23.863 回答
0

DataSet 实现IDisposable了 ,但它们抑制了它们的终结。
所以真的不需要,他们没有引入任何非托管代码。
不要用using语句包装它,但是不要忘记using在 sql 连接或数据读取器周围使用关键字。

于 2012-05-29T07:25:35.857 回答
0

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);
}

现在使用usingSataSet会很有意义。

于 2012-05-29T07:41:01.540 回答
-1

是的,绝对可以在 using 块中使用任何对象初始化代码。使用它没有副作用。在任何情况下,如果您想 100% 确定对象的垃圾收集,请将其保留在 using 块中。

于 2012-05-29T07:23:47.327 回答