我在MSDN上找到了以下代码:
public class DisposeExample
{
public class MyResource: IDisposable
{
private IntPtr handle;
private Component component = new Component();
private bool disposed = false;
public MyResource(IntPtr handle)
{
this.handle = handle;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
CloseHandle(handle);
handle = IntPtr.Zero;
disposed = true;
}
}
~MyResource()
{
Dispose(false);
}
}
public static void Main()
{
MyResource obj = new MyResource()
//obj.dispose()
}
}
现在我在这里的困惑是,如果我调用obj.dispose,它会处理在MyResources类中创建的对象,即句柄,组件等。但obj是否也会从堆中删除?析构函数也是如此。如果我不调用dispose,析构函数将在某个时候被调用。析构函数内的代码删除包含的对象。但是对象怎么样? 其次,如果我没有在类中定义析构函数并且我甚至不调用dispose,那么GC是否从未在此处出现过?
答案 0 :(得分:0)
存在IDisposable以从托管对象中删除非托管项目。运行时自动提供析构函数,这里的析构函数的唯一目的是释放非托管项。只要您的对象超出范围或设置为 null 并且没有更多对它的引用,最终将由GC清除。
答案 1 :(得分:0)
我建议使用IDisposable的基本规则是,在任何给定的时刻,对于实现IDisposable的每个对象,应该只有一个实体具有明确定义的责任,以确保它将被清理(几乎总是通过调用Dispose
)才能放弃它。这样的责任最初属于任何实体调用IDidposable
对象的构造函数,但该实体可能将责任移交给其他实体(可能会再次将其移交等)。
总的来说,我猜大多数程序员如果假装终结器并且不存在析构函数,那么他们将获得最佳服务。它们通常只是由于编写得不好的代码而需要,并且在大多数情况下,人们必须花费大量精力编写100%正确的终结器/析构函数并完成与线程上下文,意外复活等相关的所有棘手问题。可以更好地用于确保始终遵循上面给出的主要规则。由于框架及其语言中的一些不幸的设计决策,有一些情况在没有终结器/析构函数的情况下无法很好地处理,但是在大多数情况下它们用于将相对快速失败的代码转换为代码主要是工作,但有时可能会以几乎无法调试的方式失败。