Published on

Updated

Understanding Garbage Collection

Memory management in .NET πŸ’¨

Garbage collection handles much of the memory management that would otherwise require manual allocation and deallocation. It makes our work easier, but understanding its limits helps us write better software.

Originally published in January 2023; technical explanations updated on 3 October 2026.

What is garbage collection? πŸ€”

The .NET garbage collector reclaims managed memory occupied by objects that the application can no longer reach. Losing a reference does not immediately free an object: reclamation happens during a collection.

How does it work?

A collection starts from roots, such as live local variables, static fields, and runtime handles. The collector follows their references to find reachable objects. Unreachable objects can be reclaimed, and surviving objects may be moved to compact memory. Collections respond to factors such as allocation pressure and memory conditions, rather than simply running on a fixed timer.

Reference-type instances normally occupy the managed heap. Value types can be stored within other objects or arrays as well as in local storage; they are not always allocated on the stack. Boxing a value type creates a heap object containing its value. Choose types for their semantics and measure performance rather than assuming that every struct avoids heap allocation. Microsoft's ValueType documentation explains boxing.

Generational garbage collection

The managed heap uses generations 0, 1, and 2. Most small new objects start in generation 0. Surviving objects are generally promoted, with generation 2 holding longer-lived objects. A collection of a generation also collects the younger generations. This lets the collector reclaim short-lived allocations frequently without inspecting the entire heap every time. See Microsoft's GC fundamentals.

Large objects, generally those at least 85,000 bytes, go on the large object heap and are collected with generation 2. Unlike the small object heap, it is normally swept rather than compacted, although compaction can be requested. This is an exception to the simplified idea that every new allocation begins in generation 0. Microsoft's large object heap guide covers the details.

Benefits and limits 🀟

Automatic reclamation reduces manual bookkeeping and prevents many memory management errors. It does not eliminate memory leaks. A static collection, event subscription, or cache that retains references can keep objects reachable long after they are useful.

GC also does not provide timely cleanup of unmanaged resources such as file handles. Use using, IDisposable, or IAsyncDisposable where appropriate instead of waiting for finalization. Microsoft's GC performance guide discusses retained objects, finalization, and diagnosing memory problems.

Keep allocations intentional πŸ›‘

Collections consume CPU time and can pause application threads. Avoid unnecessary allocations in hot paths, keep caches bounded, and release references when they are no longer needed. Reuse or pooling can help in measured cases, but it adds complexity and can retain memory too.

Profile before optimizing. Allocation rate, retained memory, and collection pauses tell you more than a blanket rule to replace classes with structs. Garbage collection is a useful partner, not a substitute for understanding your application's lifetime and resource usage.