Course contentsShow
← C#
Lesson 1734 of 1,90816. Performance and DiagnosticsFree lesson

Analyzing Managed Memory Leaks with WeakReferences

Students will identify how to detect and prevent object rooting in long-lived caches.

In this lesson, you will learn how to use WeakReference to break strong reference chains, preventing your long-lived caches from inadvertently causing memory leaks.

The Rooting Problem in Caches

When you implement a caching mechanism in .NET, you often store objects in a Dictionary or List. Because these collections maintain "strong references" to your objects, the Garbage Collector (GC) cannot reclaim that memory, even if the rest of your application is finished with those objects. If you aren't careful, your cache becomes a "black hole" where objects live forever, leading to an OutOfMemoryException.

Using WeakReference to Break the Chain

A WeakReference allows you to reference an object while still permitting the GC to collect it if no other strong references exist. Instead of storing the object directly, you store a wrapper.

// Instead of storing a strong reference:
private readonly Dictionary<Guid, MyData> _cache = new();

// Use a WeakReference to allow the GC to collect the object:
private readonly Dictionary<Guid, WeakReference<MyData>> _cache = new();

public MyData GetFromCache(Guid id)
{
    if (_cache.TryGetValue(id, out var weakRef) && weakRef.TryGetTarget(out var data))
    {
        return data; // Object is still alive
    }
    return null; // Object was collected
}

Why This Prevents Leaks

When the system is under memory pressure, the GC identifies objects that are only reachable via WeakReference and clears them. By using WeakReference, you effectively tell the runtime: "I’d like to keep this object around for performance, but if memory gets tight, feel free to delete it."

This technique is vital for long-lived caches (like those in static utility classes or singleton services) where you want to cache data but cannot predict the lifecycle of the consumer. It shifts the responsibility of cleanup from your manual management to the built-in, highly optimized GC mechanism.

Key Takeaway: Use WeakReference for long-lived caches to ensure that your caching strategy doesn't block the Garbage Collector from reclaiming memory that is no longer needed by the rest of the application.