Search code examples
c#objectmemory-managementmemory-leaksdestroy

Determine if Object has been destroyed (i.e no longer found anywhere) in C#


I'm sure this has been asked before and I just don't know the right terms to search for. In a C# program I am working on I have an List that keeps track of Objects. Those objects can also be displayed on the screen via references by other objects.

Sometimes after an object is removed from the list it is still temporarily available to those other objects (as it should be)... After those objects are done however I want to make sure the object is 100% gone and not staying in memory still being referenced by a forgotten object... How can I do this?

To be clear, this doesn't need to happen as part of the shipped program, only for debugging.


Solution

  • You normally can't. The GC is meant to take care of memory management behind the scenes, and does it's job very specifically and by means best not trifled with. In particular, other parts of your code may keep a reference to the item you want removed, which SHOULD prevent its collection. such is the nature of memory managed languages such as C#.

    That being said, however, there are a few ways to check for when an object is disposed. The easiest to to create a simple destructor and breakpoint it, allowing you to "see" whenever an object is collected.

    ~MyClass()
    { // Breakpoint here
    }
    

    The other way is to make a static list of WeakReferences to your objects, which each object subscribes to when it's created. Make sure to keep that other list, however, as a weak reference is specifically designed to allow garbage collection, allowing you to track an object to its destruction. The other list is necessary to keep the objects alive. Also note that in .NET 4.5, there is a generic version of WeakReference. EDIT: This is definitely the solution I recommend after seeing the updates to your question. You can also quickly query which objects are still being refernced via Linq

    var leftoverObjects = WeakCache
        .Select(wr => wr.Target)
        .OfType<MyObject>() // Only if you're not using that Generic Weak Reference
        .Except(ObjectList); // filters away objects in the List
    

    Be warned the above query creates a result which has strong references, so once run, it'll keep those objects in memory as long as the result is referenced.

    If you have some sort of unmanaged memory backing your object, that's exactly what the IDisposable interface is designed for.

    UPDATE: finally, if you MUST do so, you can Force the GC to Collect. This is often heavily advised against, as you start to warp the Generations that help optimize the GC in the first place.