Question

Is it legal to write the following in .net ?

   public class A
    {
        public int i = 0;
        ~A()
        {
            Aref = this;
        }
    }


    public static A Aref;
    static void Main(string[] args)
    {
        Aref = new A();
        int gen = GC.GetGeneration(Aref);
        Aref = null;
        GC.Collect(gen, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        Console.WriteLine(Aref.i);
        Console.ReadLine();
    }

It works and writes '0' to the console as expected, but I'm wondering if it's guaranteed to always work.

Does someone know what's happening behind the scene?

Was it helpful?

Solution

It's called resurrection, and it's legal. Google for ".net object resurrection" (and terms like it) and you'll find stuff like:

Resurrection and the .NET Garbage collector

Object Resurrection

Just make sure these zombie objects don't come back and try to eat your brain or something. Like all necromancy, this is dangerous stuff. (Mostly because the finalizers higher up in the class hierarchy can have released some essential resource. Also note that the finalizer won't be run a second time if the object gets "unreferenced", unless you call GC.ReRegisterForFinalize.)

OTHER TIPS

It works because the first garbage collection doesn't collect the instance. It just schedules the instance to have its finalizer run. The finalizer then creates a new root to the instance, so when the next collection happens the instance is actually rooted and thus not up for collection.

You should be very careful with this tough. If the finalizer is used to make sure an object is disposed, this actually violates the protocol because the disposable patterns says that a disposed instance should throw an ObjectDisposedException if it is used after being disposed.

The garbage collector divides objects into three groups:

  1. Those which are still alive, because at last check a rooted reference existed outside the finalization queue;
  2. Those which need to be deleted, because no rooted reference exists anywhere;
  3. Those which need to be finalized, because a rooted reference exists in the finalization queue, but nowhere else.
Objects cannot be deleted unless there's no rooted reference anywhere. Finalization is a distinct stage before deletion; note that while an object is registered for finalization, all objects it references directly or indirectly will be protected from deletion, but not from finalization.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top