我正在阅读一些关于Dispose()
方法的文章,并发现非托管资源应该从Dispose()
方法(或finalize()方法)中显式释放。文章说文件句柄和数据库连接对象是非托管资源的例子。有人能解释一下为什么它们是非托管资源,如果在Dispose()中没有正确处理会发生什么吗?我不知道文件句柄是什么,它们存在于哪里?
我正在阅读一些关于Dispose()
方法的文章,并发现非托管资源应该从Dispose()
方法(或finalize()方法)中显式释放。文章说文件句柄和数据库连接对象是非托管资源的例子。有人能解释一下为什么它们是非托管资源,如果在Dispose()中没有正确处理会发生什么吗?我不知道文件句柄是什么,它们存在于哪里?
在这个背景下,或许最容易理解的方式是:
未托管的资源是指通过调用返回必须在某个时刻释放Windows Handle
的 Windows API 调用获得的任何资源。
唯一的其他类型资源是内存。如果 .Net 分配了内存,则可以自动进行管理。(请注意,有使用 Windows API 分配内存的方法;这被视为未托管的资源。)
例如,FileStream
类调用 Windows API 打开文件,因此 FileStream
在内部维护了一个文件句柄。该文件句柄表示必须在某个时刻释放的未托管资源。
FileStream
在后台使用了 Windows API 函数CreateFile()
。由CreateFile
返回的句柄表示未托管的资源。
如果您不释放这些句柄,则它们将在程序运行期间保持分配状态,但所有具有未托管资源的 .Net 类都提供了一个Finalizer
(请参阅下文),以确保它们通常会在某个时刻被释放。
(但是,如果您编写自己的文件处理类并忘记在任何地方释放文件句柄,该文件将保持打开状态,直到程序退出。)
通常情况下,这些未托管资源将在两个位置被释放:
Dispose()
方法。这应该是正常处理未托管资源的方式。
Finalizer
。这是一种最后的手段。如果一个类拥有 finalizer,当垃圾回收器清理一个已经死亡的对象时它将被调用。任何拥有非托管资源的类应该拥有 finalizer,以便在程序员忘记调用 Dispose() 方法时进行清理。
这有点简化了,但我希望这能帮助您理解。
有关完整细节,请参见此处的 MSDN 文章。