C#/ CLI:如果在其中使用Dispose(),则不会调用析构函数

时间:2013-06-06 15:35:45

标签: c# c++ command-line-interface destructor dispose

我有一个名为“CTransferManaged”的C ++ / CLI类,带有实现的终结器和析构函数:

CTransferManaged::~CTransferManaged()
{
    this->!CTransferManaged();
}
CTransferManaged::!CTransferManaged()
{
    //Clean up resources... 
}

此类包含一个名为“CTransfer”的C#类,其中包含一个CTransferManaged类型的对象m_transfer。

如果此类的析构函数只清除对象m_transfer的引用,我可以看到析构函数被调用(命中断点):

~CTransfer()
{
    m_transfer = null; //breakpoint on this line
}

如果我调用m_transfer对象的Dispose()函数而不更改其他任何东西,则不再调用析构函数(断点不再命中)。任何猜测为什么?

~CTransfer()
{
    m_transfer.Dispose(); //breakpoint on this line
    m_transfer = null;
}

我想手动调用Dispose(),因为我发现如果我不手动调用Dispose,则不会正确清理C ++ / CLI对象(m_transfer)的资源。目前我不知道究竟是为什么。

为什么一旦调用CTransferManaged :: Dispose()(C ++ / CLI)就不再调用CTransfer(C#类)的析构函数?

2 个答案:

答案 0 :(得分:0)

C#析构函数只能被垃圾收集器调用,你不能直接调用它。

作为IDisposalbe接口一部分的Dispose只能手动调用,不会触发析构函数。

不是依赖析构函数,而是尝试实现iDisposabe并直接调用Dispose方法并将代码放在那里。

如果Resource类包含应该处理的嵌入对象,则需要使用C#:

这种模式
// C#
public class Resource : IDisposable
{
   private EmbeddedResource embedded;

   public Resource()
   {
      Console.WriteLine("allocating resource");
      embedded = new EmbeddedResource();
   }

   ~Resource()
   {
      Dispose(false);
   }

   protected virtual void Dispose(bool disposing)
   {
      Console.WriteLine("release resource");
      if (disposing)
      {
         embedded.Dispose();
      }
   }

   public void Dispose()
   {
      Dispose(true);
   }
}

答案 1 :(得分:0)

Disposing和Finalizing的典型模式是,当您调用Dispose时,应该抑制终结器。 Dispose用于在执行后立即清除资源,而终结器用于在垃圾收集器收集类时清除资源...两者都旨在执行相同的操作(释放非托管资源),因此如果您调用处理,调用终结器将是多余的和不必要的,并且还将导致对象比它需要的寿命更长,因为它在被收集和销毁之前首先被放置在Finalizer队列上。这会导致在高度访问的应用程序上进行糟糕的内存管理,这些应用程因此,C#中的大多数Dispose方法都会调用:

GC.SuppressFinalize(this);

告诉垃圾收集器不做终结器。这种模式被广泛使用,也可能在你的非托管类中使用。这可能就是Dispose调用消除了析构函数的原因。