How does garbage collection work in C# and what are its generations?
Learn how garbage collection works in C#, how the CLR uses generations 0, 1 and 2, mark-and-compact, the Large Object Heap, and why it keeps apps fast.
Expected Interview Answer
Garbage collection in C# is the CLR's automatic memory manager that tracks object references, reclaims memory occupied by objects no longer reachable from the application's roots, and organizes the managed heap into three generations (0, 1, and 2) to collect short-lived objects efficiently.
The GC starts from roots (static fields, local variables, CPU registers), marks every reachable object, then compacts the heap and frees unreachable objects. New objects begin in generation 0; those that survive a collection are promoted to generation 1, and long-lived survivors reach generation 2. Because most objects die young, the GC collects gen 0 frequently and cheaply while collecting gen 2 rarely. Large objects (≥ 85,000 bytes) go on a separate Large Object Heap that is collected with gen 2 and is not compacted by default.
- Frees developers from manual memory deallocation
- Generational design makes collecting short-lived objects fast
- Compaction reduces heap fragmentation
- Reduces memory leaks and dangling-pointer bugs
- Tunable modes (workstation, server, concurrent) fit different workloads
AI Mentor Explanation
Think of the GC as a groundsman clearing kit off the field. Newly used gear sits at the boundary (gen 0) and is checked after every over because most of it is done with quickly. Gear still in use gets moved to the dressing room (gen 1), and permanent equipment goes to the store (gen 2), which is tidied only occasionally. The rarely-touched store is swept least, keeping match cleanups fast.
Step-by-Step Explanation
Step 1
Allocate in gen 0
Every new object is placed on the generation 0 segment of the managed heap, which is small and fast.
Step 2
Mark reachable objects
When gen 0 fills, the GC walks from roots (statics, locals, registers) and marks every object still reachable.
Step 3
Sweep and compact
Unreachable objects are freed and survivors are compacted together to remove gaps and fragmentation.
Step 4
Promote survivors
Objects that survive gen 0 are promoted to gen 1, and gen 1 survivors are promoted to gen 2.
Step 5
Collect higher gens rarely
Gen 1 and gen 2 (plus the Large Object Heap) are collected far less often, keeping frequent gen 0 collections cheap.
What Interviewer Expects
- That the GC reclaims memory of unreachable objects starting from roots
- Correct explanation of generations 0, 1, and 2 and promotion
- Why generational collection is efficient (most objects die young)
- Awareness of the mark-and-compact process
- Knowledge of the Large Object Heap and its threshold
Common Mistakes
- Saying the GC uses reference counting like some other runtimes
- Claiming you can force precise, immediate collection reliably in production
- Confusing IDisposable/Dispose with garbage collection
- Thinking objects are collected the moment they go out of scope
- Forgetting that the Large Object Heap is collected with gen 2 and not compacted by default
Best Answer (HR Friendly)
“Garbage collection is .NET's way of automatically cleaning up memory that a program no longer uses, so developers don't have to free it by hand. It sorts objects into generations — new, medium, and old — and cleans the newest ones most often because they usually stop being needed quickly, which keeps the program fast.”
Code Example
using System;
class GcDemo
{
static void Main()
{
object obj = new object();
// A new object starts in generation 0
Console.WriteLine($"Gen: {GC.GetGeneration(obj)}"); // 0
// Force a collection (for demonstration only, not for production)
GC.Collect();
GC.WaitForPendingFinalizers();
// Surviving object is promoted to a higher generation
Console.WriteLine($"Gen after collect: {GC.GetGeneration(obj)}"); // 1
// Inspect how many collections each generation has had
Console.WriteLine($"Gen0 collections: {GC.CollectionCount(0)}");
Console.WriteLine($"Gen2 collections: {GC.CollectionCount(2)}");
}
}Follow-up Questions
- Why are most objects expected to die in generation 0?
- What is the Large Object Heap and why isn't it compacted by default?
- What is the difference between workstation and server GC?
- How do finalizers affect an object's collection?
- When, if ever, is it appropriate to call GC.Collect() manually?
MCQ Practice
1. Which generation holds newly allocated objects?
New objects are allocated in generation 0, which the GC collects most frequently.
2. Why is generational GC efficient?
Most objects are short-lived, so frequently collecting the small gen 0 reclaims most memory cheaply.
3. Objects larger than about 85,000 bytes are placed on:
Large objects go on the Large Object Heap, which is collected with gen 2 and not compacted by default.
Flash Cards
How does .NET's GC find garbage? — It marks objects reachable from roots (statics, locals, registers); everything unmarked is collected.
What are the three generations? — Gen 0 for new objects, gen 1 for short-lived survivors, gen 2 for long-lived objects.
Why collect gen 0 most often? — Most objects die young, so cheap frequent gen 0 collections reclaim the bulk of garbage.
What is the Large Object Heap? — A separate heap for objects ≥ 85,000 bytes, collected with gen 2 and not compacted by default.
Does Dispose trigger the GC? — No — Dispose releases resources deterministically; the GC reclaims managed memory independently.
Continue Learning
Related Interview Questions
What is the difference between managed and unmanaged code in C#?
medium
What are the boxing and unboxing operations in C# and why do they matter?
medium
What is the IDisposable interface and the using statement in C#?
medium
What is the Large Object Heap, and how do server GC and workstation GC change your application's behaviour?
hard