我正在尝试理解可以通过代码明确完成的内存过程的发布。
我在下面的MS线程中看到Dispose方法在Component类中实现。在这里,我有三个疑问。
组件类派生自IDisposable,但是,在这个类库中,我发现它没有实现方法Dispose,甚至看起来都不是“public void Dispose(){}”。但是,当我只是编写一个类并声明一个没有任何主体的方法时,它给出了编译时错误说,我应该定义正文或使其成为抽象。为什么会有这种差异?
我通常用这种方式,例如“connection.Dispose();”在finally块中配置sqlconnection。据我所知,SqlConnection派生自DBConnection,而DBConnection又派生自Component。当我查看Component类时,我只看到方法声明“public void Dispose();”然后它实际实现的地方?
我还看到一些专门实现的代码,如下面MS网站中给出的代码。它们为Dispose状态声明了一个bool变量,并有一个新的Dispose方法,它们在对象上调用Component Dispose。他们还使用Kernel32方法CloseHandle作为非托管资源。这种方法有什么用?在处理它时,我从未将它用于我的SqlConnection(也是一个非托管资源)。
http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize(v=vs.110).aspx
有人可以帮我理解上面的三个问题。我正在学习所有这些。谢谢
答案 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()
:
请注意以下内容:
调用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模式的部分目的是提供一个标准的位置来放置这种东西,这样你作为程序员就不需要知道这些东西来正确处理对象。