As a C++ fan, I'm a long time admirer for deterministic finalization. I think introduction of garbage collection to C style language by Java and .Net is a huge improvement. However, I found lose of deterministic destructor is almost unacceptable when I first enter Java/.Net world. Of course I'm used to it now, but it's still quite confusing to me for C# to use C++ destructor syntax for Finalizer. And in managed extension of C++, destructor becomes something totally different for managed data type. I bet a lot of experienced C++ developers make mistake to use finalizer as if it was destructor when they first try .Net. So when I read the new changes in Whidbey version of C++ from Stan Lippman's blog, I'm very excited and can't wait to give it a try.

But before we look into the new features, let's go over how old version of managed C++ handles destructors. I wrote this simple program:

#using <mscorlib.dll>

using namespace System;

__gc class RefT
{
public:
   RefT () {Console::WriteLine ("RefT::RefT");}
   ~RefT () {Console::WriteLine ("RefT::~RefT");}
};

 

__value class ValueT

    ValueT () {Console::WriteLine ("ValueT::ValueT");}
    //destructor is not allowed for value type
};

int main()

    { //1. auto-generated finalizer will be called in asynchronizied fashion
        RefT * prt = new RefT;
    }


   { //2. Dispose is called at “delete” and finalizer will be suppressed
       RefT * prt = new RefT;
       delete prt;
   }

  {
      ValueT vt;
   }
 
  {
      //value type can't be created in GC heap
      ValueT * pvt = __nogc new ValueT;
      delete pvt;
   }
   return 0;
}

I compiled it with V1.1 C++ compiler and checked generated IL code using ildasm. RefT is compiled to something like this:

class RefT
{
    RefT ()
   {
       Console.WriteLine (“RefT::RefT”);
   }

   void Finalize ()
   {
       Console.WriteLine (“Ref::~Ref”);
   }

   void __dtor ()
   {
       GC.SuppressFinalize (this);
       Finalize ();
   }
}

Here we could see that C++ destructor is mapped to CLR finalizer and a method “__dtor” is added to call finalizer and SupressFinalize.

In main, the first block creates a RefT object in heap and leaves it as garbage. Sometime later, finalizer (~RefT) will run and the object will be collected. In the second block, we “delete” the object. This is translated into a call to __dtor in IL. So “delete” acts more like Dispose method recommended by IDisposable pattern: the object is not freed but the contents are disposed and finalizer won't run on the object later.