在Component类库中实现的Dispose方法在哪里

时间:2013-11-10 20:01:46

标签: c# .net c#-4.0 interface garbage-collection

我正在尝试理解可以通过代码明确完成的内存过程的发布。

我在下面的MS线程中看到Dispose方法在Component类中实现。在这里,我有三个疑问。

  1. 组件类派生自IDisposable,但是,在这个类库中,我发现它没有实现方法Dispose,甚至看起来都不是“public void Dispose(){}”。但是,当我只是编写一个类并声明一个没有任何主体的方法时,它给出了编译时错误说,我应该定义正文或使其成为抽象。为什么会有这种差异?

  2. 我通常用这种方式,例如“connection.Dispose();”在finally块中配置sqlconnection。据我所知,SqlConnection派生自DBConnection,而DBConnection又派生自Component。当我查看Component类时,我只看到方法声明“public void Dispose();”然后它实际实现的地方?

  3. 我还看到一些专门实现的代码,如下面MS网站中给出的代码。它们为Dispose状态声明了一个bool变量,并有一个新的Dispose方法,它们在对象上调用Component Dispose。他们还使用Kernel32方法CloseHandle作为非托管资源。这种方法有什么用?在处理它时,我从未将它用于我的SqlConnection(也是一个非托管资源)。

  4. http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx

    有人可以帮我理解上面的三个问题。我正在学习所有这些。谢谢

2 个答案:

答案 0 :(得分:3)

首先:

public void Dispose() { }

拥有一个正文 - 它只是一个空洞。这里没有区别。实际上,虽然Component.Dispose是:

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

如果您想添加逻辑,我们的想法是override protected virtual void Dispose(bool disposing)方法。

其次,如果你这样打connection.Dispose(),那么你做错了。您应该使用using块:

using(var conn = ...)
{
    conn.Open();
    using(var cmd = conn.CreateCommand())
    {
        // etc etc
    }
    // look ma, no finally
}

您的第三点,以及您引用的MSDN文章,只是您实际需要执行此操作的示例。 CloseHandle方法只是非托管资源的示例。这是关键,因为您不使用终结器来清理托管资源 - 只有未损坏的。因此,涉及非托管句柄的示例很简单,可以说明:

  • 从终结者调用Dispose(false)
  • override Dispose(bool)方法
  • 从终结器和处理中清除一些代码(句柄)(另外,Dispose(false)Dispose(true)
  • 有一些代码仅针对Dispose(true)案件执行 - 即继续处置

答案 1 :(得分:1)

首先要明确的是Dispose()绝对 NOTHING 与内存有关。 IDisposable模式完全是关于清理非托管资源......也就是说,清除除内存之外的所有内容

这里记录了

Component.Dispose()

  

http://msdn.microsoft.com/en-us/library/3cc9y48w.aspx

请注意以下内容:

  

调用Dispose后,必须释放对Component的所有引用,以便垃圾收集器可以回收Component占用的内存。

同样,我们看到Dispose() - 一个对象是一个与释放内存不同的问题。

SqlConnection的情况下,在工作中存在继承层次结构。 Dispose()类型本身有一个空的Component方法(空方法是合法的)。该方法为空,因为基类本身不需要担心任何非托管资源。 SqlConnection类型会覆盖基础实现,以便关闭与服务器的连接。

现在让我们谈谈终结者。终结器也与内存无关,除了它们被垃圾收集器调用。终结器的目的是在收集对象时释放非托管(非内存)资源。如果您正在构建一个使用丰富的非托管资源的类,这样就不存在争用或耗尽资源的风险,终结器本身就足够了,并且Dispose()没有用处。但是,几乎所有计算资源都有一定程度的稀缺性,因此您可能不希望在发布之前等待垃圾收集器。垃圾收集器可能在一段时间内不收集对象,因此存在Dispose()模式以提供一种以及时,可预测的方式释放非托管资源的方法。

商品新闻是,大多数时候,你不需要担心终结者。如果要构建一种全新的非托管资源,则只需要实现终结器。例如,如果程序中有一个类型通过包装SqlConnection类来管理与Sql Server数据库的连接,则不需要终结器。这可能是一个新类,但SqlConnection类型最终处理释放数据库连接。但是,您应该在类型中实现或使用IDisposable,以便及时释放它管理的连接。另一方面,如果您正在构建一种全新的数据库引擎以与Sql Server竞争,或者从头开始重新实现Sql Server连接协议,那么您需要一个终结器。

有时,您的Dispose()方法需要抑制完成。例如,如果您在处理完第二次后尝试释放非托管资源,则可能会导致不必要的异常。

我想我已经从你的三个问题中涵盖了大部分要点,但还有一些问题需要解决:

  

它看起来像“public void Dispose(){}”。但是当我只是编写一个类并声明一个没有任何主体的方法时,它给出了编译时错误说,我应该定义正文

那种方法有一个身体。 { } 方法的主体。只是它是空的。

  

[SqlConnection.Dispose()]实际实现在哪里?

您正在查看IDE。这只显示了方法声明和基本描述。那里有更多的代码。如果您真的需要,full .Net source code可用。

  

他们还使用Kernel32方法CloseHandle作为非托管资源。这种方法有什么用?

这只是一种特定于处理特定类型资源的方法。 IDisposable模式的部分目的是提供一个标准的位置来放置这种东西,这样你作为程序员就不需要知道这些东西来正确处理对象。