C# 关于C中Dispose()和析构函数的两个问题#
我有一个关于如何使用C# 关于C中Dispose()和析构函数的两个问题#,c#,.net,dispose,destructor,finalizer,C#,.net,Dispose,Destructor,Finalizer,我有一个关于如何使用Dispose()和析构函数的问题。阅读一些文章和MSDN,这似乎是实现Dispose()和析构函数的推荐方法 但我有两个关于此实现的问题,您可以在下面阅读: class Testing : IDisposable { bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!_disposed) // only dispose once
Dispose()
和析构函数的问题。阅读一些文章和MSDN,这似乎是实现Dispose()
和析构函数的推荐方法
但我有两个关于此实现的问题,您可以在下面阅读:
class Testing : IDisposable
{
bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed) // only dispose once!
{
if (disposing)
{
// Not in destructor, OK to reference other objects
}
// perform cleanup for this object
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
// tell the GC not to finalize
GC.SuppressFinalize(this);
}
~Testing()
{
Dispose(false);
}
}
Dispose()上的GC.superssFinalize(this)
当程序员使用using
或显式调用Dispose()时,我们的类正在调用GC.supersfinalize(this)
。我的问题是:
- 这到底是什么意思?是否收集对象,但不调用析构函数?。我猜anwswer是肯定的,因为它们被框架转换为Finalize()调用,但我不确定
Dispose()
- 我们为什么不在这一点上处理资源呢?换句话说,为什么我们不能释放析构函数上的资源
- 哪些代码必须在if内部执行,哪些代码必须在外部执行
if (!_disposed) // only dispose once! { if (disposing) { //What should I do here and why? } // And what here and why? }
if(disposing)
中,调用\u myField.Dispose()
换句话说,处置托管的资源(具有Dispose属性的对象)
在外部,调用代码清理(close)非托管资源,如Win32API.close(_myHandle)
请注意,当您没有非托管资源时,通常情况下(查找SafeHandle),您不需要析构函数,因此不需要SuppressFinalize
这使得这个模式的完整(官方)实现只需要从继承测试的可能性来实现。请注意,
Dispose(bool)
受到保护。当您声明类测试是密封的时,省略~Testing()
是完全安全的 第一部分:
当调用GC.superssFinalize(this)
时,GC被告知该对象已经释放了它的资源,并且可以像任何其他对象一样进行垃圾收集。是的,终结和“析构函数”在.NET中是一样的
第二部分:
终结是由一个单独的线程完成的,我们无法控制终结的时间和顺序,因此我们不知道是否还有其他对象可用或已经终结。因此,您不能引用
disposing
块之外的其他对象。绝大多数情况下,当拥有IDisposable
资源的对象最终确定时,以下语句中至少有一条将应用于这些资源:
在一些罕见的情况下,上面没有应用,在终结器中清理可能是合适的,但是除非首先检查了以上四种可能性,否则不应该考虑它。对于非托管资源,您通常应该使用
SafeHandle
,而托管资源通常不需要终结器。@codein,您是对的,但是在MSDN上有什么规范性的评论吗?@CodeInChaos:请您提供一些关于它的文献,好吗?我个人同意一个学派的观点,即(非关键)终结器应该做的是通知程序员一个潜在的错误。我手头没有规范参考,但有几个博客描述了正常终结的问题(特别是它不总是执行,很难编码)或者safehandles/critical finalization的优点@Henk:编辑后大约2a:Than意味着即使程序员忘记调用dispose,非托管资源也会被清理掉?-1这是错误的。您不能在Finalizer中处理资源。引用可能无效,因此您不能触摸它们。@Guffa:引用不能变为无效只要您持有id,类型安全性就会一直保持到最终确定fase。这很棘手:myField可能已经被处置(但没有被收集!)。Dispose()在一个已处理的对象上应该是安全的。@Guffa:我认为Henk是正确的,因为他指的是disposing
块中的dispose托管对象,而这不是终结器,是dispose()
程序员发出的呼叫。Henk是对的,但是……值得再次强调的是,通过引用Finalizer中的托管IDisposable
资源,您可以人为地使其生存更长时间。如果您没有在Finalizer中引用它,GC将可以免费收集它(如果有,请致电其后备定稿人。)