0

我在 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,则有时会调用析构函数。析构函数中的代码删除了包含的对象。但是obj呢?其次,如果我没有在类中定义析构函数并且我什至不调用 dispose,那么 GC 是否永远不会出现在这里?

4

2 回答 2

0

IDisposable 的存在是为了从您的托管对象中删除非托管项目。运行时自动提供了一个析构函数,这个析构函数在这里的唯一目的是释放非托管项。一旦您的对象超出范围或设置为null并且没有更多对其的引用,最终将被 GC 清除。

于 2013-02-08T08:04:42.917 回答
0

我建议使用 IDisposable 的基本规则是,在任何给定的时间,对于实现 IDisposable 的每个对象,都应该有一个明确定义的实体负责确保它被清理(几乎总是通过调用Dispose) 在它被放弃之前。这种责任最初将属于调用IDidposable对象构造函数的任何实体,但该实体可能会将责任移交给其他实体(可能会再次将其移交,等等)。

一般来说,我猜大多数程序员如果假装终结器和析构函数不存在,他们会得到最好的服务。它们通常只在代码编写不佳的情况下才需要,并且在大多数情况下,人们必须花费精力编写 100% 正确的终结器/析构函数并解决与线程上下文、意外复活等相关的所有棘手问题. 可以更好地确保始终遵循上面给出的主要规则。由于框架及其语言中的一些不幸的设计决策,有一些情况在没有终结器/析构函数的情况下无法很好地处理,但在大多数情况下,它们用于将相对较快失败的代码转换为将大部分工作,但有时可能会以几乎无法调试的方式失败。

于 2013-02-08T17:21:31.320 回答