0

I was experimenting using the WeakReference class but I didn't expect that it doesn't keep the object from the next garbage collection. Why?

I don't have the knowledge of the practical use of this class.

The code forces another garbage collection after I set the myObject to null.

Edit: On the end of else if line the myObject is not disposed, is it because the compiler knows that WeakReference wr object is still used in the code so that the garbage collection does not reclaim it?

 class Program
{
    static void Main(string[] args)
    {
        MyObject myObject = new MyObject(25);
        WeakReference wr = new WeakReference(myObject);

        if (wr.IsAlive) Console.WriteLine("Alive");

        myObject = null;

        GC.Collect();
        if (wr.IsAlive) Console.WriteLine("Still alive");
        else if(!wr.IsAlive) Console.WriteLine("Dead");

        //
        //edit: added this 
        GC.Collect();
        if (wr.IsAlive) Console.WriteLine("Still alive");
        else if (!wr.IsAlive) Console.WriteLine("Dead");
        //edit end
        Console.ReadKey();
    }
}

class MyObject : IDisposable
{
    private bool disposed = false;
    private int id = 0;
    public MyObject(int id)
    {
        this.id = id;
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {
        Console.WriteLine("disposed {0}", id);
        if (!disposed)
        {
            if (disposing)
            {
                //free managed
            }
            //free unmanaged
            disposed = true;
        }
    }

    ~MyObject()
    {
        Dispose(false);
    }
}
Ronald Abellano
  • 774
  • 10
  • 34
  • 1
    You should add the output of your test application to the question. Otherwise it's a bit of guesswork where exactly your problem happens (although I do have a clue). – PMF Mar 19 '19 at 14:32
  • 1
    But.. this is exact the purpose of weak references, they are "alive" until the target is alive. Thus, they can't "keep the object frtom the next GC" as it would contradict their purpose. – Konrad Kokosa Mar 19 '19 at 14:38
  • @PMF I've edited the description and the code for a little test. What I've observed is maybe that "wr" variable is still used at the end of the code. If you remove the edited added code the myObject is disposed. – Ronald Abellano Mar 19 '19 at 14:42
  • Your object has a finalizer, so you need to call `GC.WaitForPendingFinalizers()` after the `GC.Collect()` call to see the effect. Note that `GC.Collect()` is not necessarily a synchronous operation. – PMF Mar 19 '19 at 14:46

2 Answers2

0

On the end of else if line the myObject is not disposed, is it because the compiler knows that WeakReference wr object is still used in the code so that the garbage collection does not reclaim it?

No, it is because you run the application with a debugger attached. Please read @Hans Passant's answer here for details.

If you build the application in release mode and run it without a debugger attached, you should see "Alive", "Dead" and "Dead" being printed to the console. I do.

You should also remove the finalizer from your MyObject class since you are using no unmanaged resources.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • 1
    Using finalizer is good indicator as it makes difference of when the object actually dies. I suppose it's presented here for the demo purposes. – Dmytro Mukalov Mar 19 '19 at 14:56
0

The short answer why your object doesn't survive the first collection: there are 2 types of weak references: short and long. The short are collected immediately while long are collected only when their finalizers complete - that is a long weak reference should have finalizer which is true for your case but another obligatory requirement is that it should be constructed with trackResurrection parameter set to true (default is false). The finalizers are executed during the second collection anyway but with trackResurrection set to false the object isn't tracked and its reference is set to null (however formally it's alive until the finalization but cannot be accessed).

Dmytro Mukalov
  • 1,949
  • 1
  • 9
  • 14