MZywitza
MZywitza

Reputation: 3111

Garbage collector won't collect an object created with using

I want to test for object references held improperly and wrote a test that always failed. I simplified the test to the following behaviour:

    [Test]
    public void ScopesAreNotLeaking()
    {
        WeakReference weakRef;
        Stub scope = null;
        using (scope = new Stub())
        {
            weakRef = new WeakReference(scope);
        }
        scope = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Assert.That(weakRef.Target, Is.Null);
    }

This test however, which does the same without using, passes:

    [Test]
    public void ScopesAreNotLeaking()
    {
        WeakReference weakRef;
        Stub scope = new Stub();
        weakRef = new WeakReference(scope);
        scope = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Assert.That(weakRef.Target, Is.Null);
    }

The used stub class is simple enough:

class Stub : IDisposable
{
    public void Dispose()  {}
}

Can someone please explain me that behaviour or - even better - has an idea how to make sure that the object gets garbage collected?

PS: Bear with me if a similar question was asked before. I only examined those questions that have using in the title.

Upvotes: 6

Views: 841

Answers (4)

Sven
Sven

Reputation: 22683

I suspect there may be a local introduced by the using statement. Use ildasm to see if all the references in the function to the object are truly cleared before the call to GC.Collect. Also try to put the using bit in a separate function that returns the weak reference.

Upvotes: 2

codymanix
codymanix

Reputation: 29468

The mark & sweep GC, like it is used in .NET, is not deterministic. Even if called by GC.Collect() there is no guarantee that is really runs.

Additionally, the using-clause does not have anything to do with garbage collection. If just calls Dispose() on its target object.

Upvotes: 1

Patrick
Patrick

Reputation: 8320

using is not designed to force garbage collection but to ensure dispose is called. Dispose allows you to release non-garbage collected resources like file handles. Garbage collection happens when c# is good and ready.

Upvotes: 5

Shea Levy
Shea Levy

Reputation: 5415

Your two test cases are not identical. At the end of a using statement, the resource's Dispose method is called, it is not set to null. Calling Dispose does not necessarily call the destructor.

Upvotes: 1

Related Questions