【发布时间】:2021-01-17 13:08:24
【问题描述】:
下面是 C# 类的典型 IDisposable 实现,它同时具有托管和非托管资源。我的问题是,是否存在在任何给定对象的类的 Dispose() 方法之前调用 ~DisposableObject() 析构函数方法的情况。如果可能的话,它不会将标志设置为false,并且托管资源将永远不会有机会被释放,因为如果将dispose标志设置为false,Dispose(bool)方法不会做任何事情。
public class DisposableObject : IDisposable
{
private bool disposed;
private ManagedResource mgdRs;
private UnmanagedResource unMgdRs;
public DisposableObject()
{
mgdRs = new ManagedResource();
unMgdRs = 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
mgdRs.Dispose();
}
// clean up unmanaged resources
unMgdRs.Destroy();
this.disposed = true;
}
}
}
}
【问题讨论】:
-
docs.microsoft.com/en-us/dotnet/standard/garbage-collection/… 我发现你有点难以理解 ms 示例,一个更容易一些.. 我认为它们不完全相同。当我关注 ms 时,它会更容易,并且努力查看您是否有问题是有意义的。基本上如果它已经被调用然后处理。
-
您在问终结器是否可以在调用
Dispose()之前运行?那么是的,因为程序创建一次性对象然后从不对其调用Dispose()是合法的:语言中没有任何内容需要Dispose()被调用。如果ManagedResource有自己的终结器,那么终结器可能在DisposableObject的终结器运行时已经运行。你真的无能为力,因为finalizers might not ever run anyway。 -
析构函数可以在任何时候被调用......甚至比你想象的要早
-
修改文档相关讨论@Seabizkit 链接:The Dispose guidelines really should be updated to point developers in the right direction。很长,但你必须通读。
-
我发现官方指导非常混乱,并且总是参考 Stephen Cleary 的建议(IDisposable 上的Stephen's blog 和this codeproject article。在这种情况下:重构以便您的类只处理托管或非托管资源,然后按照链接文章中的指南进行操作。
标签: c# idisposable finalize