【问题标题】:"using" keyword in C# with datasetC# 中的“使用”关键字与数据集
【发布时间】:2012-05-29 07:14:51
【问题描述】:

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

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

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

【问题讨论】:

  • 澄清 using 语句不会强制终结器由垃圾收集器运行。 'using' 语句仅保证 IDisposable 对象的 Dispose() 方法将运行。
  • Dataset 有点特殊:stackoverflow.com/questions/913228/… "DataSet 中的 Dispose 方法仅因为继承的副作用而存在——换句话说,它实际上并没有在定稿。”

标签: c# .net interface dataset


【解决方案1】:

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

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

任何派生类型也将实现 IDisposable。如果它没有显式实现(即覆盖 IDisposable.Dispose),则会调用基方法(DataSet.Dispose)。

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

【讨论】:

  • 已经说过使用数据集的使用块是一个好习惯,是否像垃圾收集器循环会在稍后的某个时间清除内存缓存中的数据集,使用块可能会这样做工作一完成?
  • Dispose 和 Garbage collection 是不同但相关的概念。 Dispose 通常用于释放垃圾收集器没有作用的非托管资源。垃圾收集器只处理托管内存。 Dataset 内部使用了一些非托管资源,这就是它实现 Dispose 的原因。如果您没有指定 using 块,或者忘记调用 Dispose,则不会释放非托管资源。诀窍(具有性能损失)是调用 Dispose in finalizer
  • 对于你的问题,如果一个类实现了 Dispose,最好使用 using 块。
【解决方案2】:

我个人不会将它用于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

【讨论】:

  • 如果我处理数据集中的大量数据,手动强制垃圾收集是否好。虽然 CLR 稍后会处理它调用垃圾收集器?
  • IDisposable 不是 GC 的替代品。 “using”语句不进行垃圾收集,所以无论如何你都不应该担心“谁来负责垃圾收集”。
  • @Mert 我知道。 using 语句处理对象并释放 MarshalByValueComponent 使用的所有资源,如 MSDN 中所述。我说我会让 CLR 管理内存,如果他想立即进行垃圾收集,OP 可以执行 GC.Collect();
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      C# 允许您在所有实现IDisposable 的东西上使用using。为什么?因为 using 只是一种语法糖。 using(obj){/*somecode*/}其实是这样的:

      try
      {
          /*somecode*/
      }
      finally
      {
          if(obj!=null) obj.Dispose();
      }
      

      如果您使用的是 Typed 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);
      }
      

      现在在这个SataSet 上使用using 将有意义。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 垃圾收集和调用 Dispose 根本不是一回事。调用 Dispose(这是 using 语句所做的)不会导致对象被垃圾回收。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-26
        • 1970-01-01
        相关资源
        最近更新 更多