这是典型的IDispose实现。我不明白的是析构函数? 如果你的类的用户忘记调用Dispose,那么你是否会因为析构函数不会调用r1.Dispose()而导致资源泄漏?
public class DisposableObject : IDisposable
{
private bool disposed;
private UnmanagedResource r1;
public DisposableObject()
{
r1 = new UnmanagedResource();
}
~DisposableObject()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// clean up managed resources
//call dispose on your member objects
r1.Dispose();
}
// clean up unmanaged resources
this.disposed = true;
}
}
public void SomeMethod()
{
if (this.disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
}
}
答案 0 :(得分:2)
否 - 一旦对对象的所有引用都消失,GC将调用析构函数(但这不是确定性的。)
答案 1 :(得分:2)
如果r1
确实是本机资源(在您的示例中看起来不像它),则不应将其丢弃在if(disposing)块内,而是在它之后。特别注意:
if (disposing)
{
// free managed resources
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
来自Implement IDisposable Correctly - MSDN
如果r1
是具有自己的IDisposable
实现的托管资源,假设它已正确实施,任何本机资源都将在其终结器中正确清理(这就是您不需要的原因)在你自己担心它。)
答案 2 :(得分:0)
析构函数(终结器)调用Dispose的原因是垃圾收集器在收集对象之前调用它,保证至少在某个时刻释放UnmanagedResource。
通过使用using
和try...finally
,您可以强制执行资源,以便在不需要时立即处理
http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx
答案 3 :(得分:0)
如果您真的想要,可以添加终结器:
~DisposeImplementation()
{
Dispose(false);
}
但它应该仅作为真正的最后手段,而不是直接依赖的东西。
答案 4 :(得分:0)
在.Net中,我们有一个名为垃圾收集的功能。垃圾收集完成所有未引用的对象(任何更多)。你的析构函数/终结器然后调用Dispose()。
如果您的用户忘记删除这些引用,您最终会发生泄漏。
但这就是using
的用途:通过仅在需求范围内定义一次性用品来避免内存堵塞。
答案 5 :(得分:0)
模式存在是因为垃圾收集器不保证托管对象将被垃圾收集的顺序。因此,在终结器中,您无法保证r1
引用仍然有效。
您的r1
引用的类名称为UnmanagedResource
,但它显然是一种管理类型。对于真正的无人资源,您只能拥有IntPtr
或其他令牌。为了确保r1
不喜欢它的资源,它应该实现相同的Dispose模式,并在if (disposing)
检查之外释放它的非托管资源。