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

C#/CLI:如果在析构函数中使用Dispose(),则未调用析构函数,c#,c++,command-line-interface,destructor,dispose,C#,C++,Command Line Interface,Destructor,Dispose,我有一个名为“CTransferManaged”的C++/CLI类,它实现了终结器和析构函数: CTransferManaged::~CTransferManaged() { this->!CTransferManaged(); } CTransferManaged::!CTransferManaged() { //Clean up resources... } 该类用一个名为“CtrTransfer”的C#类包装,其中包含CtrTransferManaged类型的对象

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

CTransferManaged::~CTransferManaged()
{
    this->!CTransferManaged();
}
CTransferManaged::!CTransferManaged()
{
    //Clean up resources... 
}
该类用一个名为“CtrTransfer”的C#类包装,其中包含CtrTransferManaged类型的对象m#U传输

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

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

~CTransfer()
{
    m_transfer.Dispose(); //breakpoint on this line
    m_transfer = null;
}
我想手动调用Dispose(),因为我发现如果我不手动调用Dispose,C++/CLI对象(m_transfer)的资源没有被正确清理。目前我不知道确切的原因

为什么CtrTransfer(C#类)的析构函数在调用CtrTransferManaged::Dispose()(C++/CLI)时不再被调用?

C#析构函数只能由垃圾收集器调用,不能直接调用

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

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

如果资源类包含应释放的嵌入对象,则C#需要此模式:


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

GC.SuppressFinalize(this);

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

CtrTransfer类必须实现IDisposable,以便能够正确地处理m_传输成员。看起来是你干的。不要为CtrTransfer实现终结器。将成员设置为null没有任何用处,调用其Dispose()方法是错误的。@HansPassant:为什么在CtrTransfer的终结器中调用成员对象(m_transfer)的Dispose()方法是错误的?正如我所提到的,我发现当我不调用Dispose()时,m#u transfer的资源没有被正确清理(注意,我不想手动清理()C#对象(类CTransfer)。我只想使用其成员m#u transfer(类CTransferManaged)的手动清理,因为它的资源没有被正确清理。
// 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);
   }
}
GC.SuppressFinalize(this);