Search code examples
c#garbage-collectionweak-references

WeakReference only keep the object in 1 generation?


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);
    }
}

Solution

  • 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.