Master C# Programming From Scratch

Clear, interactive, and structured coding lessons designed for absolute beginners.

Garbage Collection in C#

Garbage Collection (GC) is an important feature of .NET that automatically manages memory used by objects in a C# application. It identifies objects that are no longer being used and releases the memory occupied by those objects.

In simple words, Garbage Collection helps developers manage managed memory automatically, so developers do not normally need to manually free memory after every object is no longer required.

Beginner Tip: You create objects using new, but you generally do not manually delete those objects in C#. The .NET Garbage Collector manages their memory automatically.

What is Garbage Collection?

Garbage Collection is the automatic memory management mechanism provided by the .NET runtime. When an object is created, memory is allocated for that object. When the object is no longer reachable from the application, the Garbage Collector can eventually reclaim that memory.

This process reduces the need for manual memory management and helps prevent many common memory-management problems.

Why Do We Need Garbage Collection?

Applications continuously create objects while they are running. If unused objects were never removed from memory, memory usage could continuously increase.

  • Automatically manages memory used by managed objects.
  • Reclaims memory from objects that are no longer reachable.
  • Reduces the need for manual memory deallocation.
  • Helps developers focus on application logic rather than manually tracking every object's lifetime.
  • Helps reduce certain types of memory-management errors.

Garbage Collection and Managed Heap

Objects created with new are generally allocated on the managed heap. The .NET Garbage Collector monitors this managed heap and determines which objects are still reachable.

C#
class Student {
    public string Name;
}

Student student = new Student();
student.Name = "Rahul";

Here, a Student object is created using new. The object is stored in managed memory and is automatically managed by the .NET runtime.

Reachable and Unreachable Objects

The Garbage Collector primarily works based on whether objects are still reachable by the application.

If a reference still points to an object, that object is considered reachable.

C#
Student student = new Student();

student.Name = "Amit";

As long as the application can reach the object through a live reference, the Garbage Collector treats it as in use.

Example of an Unreachable Object

C#
Student student = new Student();

student.Name = "Amit";

student = null;

After assigning null to the variable, the previously created object may no longer be reachable through that reference. If there are no other references to the object, it becomes eligible for garbage collection.

Important: Becoming eligible for garbage collection does not mean that the object is removed from memory immediately. The Garbage Collector decides when collection should occur.

How Garbage Collection Works

At a high level, the Garbage Collector identifies objects that are no longer reachable and reclaims their memory.

1. Objects are created
↓
2. Objects are stored in managed memory
↓
3. Some objects become unreachable
↓
4. Garbage Collector identifies eligible objects
↓
5. Memory is reclaimed

Garbage Collection Generations

The .NET Garbage Collector uses generations to improve the efficiency of memory management. Objects are grouped based on their age and how long they have survived.

Generation Description
Generation 0 Contains newly created objects. Short-lived objects are commonly collected here.
Generation 1 Contains objects that survived a Generation 0 collection.
Generation 2 Contains longer-lived objects that have survived multiple collections.
Key Point: Garbage Collection is optimized around the idea that many objects are short-lived, while some objects remain alive for a long time.

Generation Example

Suppose an application creates many temporary objects. New objects generally begin in Generation 0. If an object survives garbage collection, it may move to a higher generation.

C#
for ( int i = 0; i < 1000; i++)
{
    var data = new Student();
}

In a real application, temporary objects may be created during processing. Objects that are no longer reachable can eventually become eligible for collection.

Using GC.Collect()

C# provides the GC.Collect() method to request a garbage collection. However, developers normally should not call it unnecessarily because the .NET runtime has its own garbage collection strategy.

C#
GC.Collect();
Important: GC.Collect() should not be treated as a normal way to clean memory after every object. The Garbage Collector is designed to automatically determine appropriate collection times.

Checking an Object's Generation

The GC.GetGeneration() method can be used to find the generation of an object.

C#
using System;

class Student
{
    public string Name;
}

class Program
{
    static void Main()
    {
        var student = new Student();

        int generation = GC.GetGeneration(student);

        Console.WriteLine(generation);
    }
}

Stack, Heap and Garbage Collection

Garbage Collection is mainly associated with the managed heap. Understanding the difference between Stack and Heap memory makes Garbage Collection easier to understand.

Stack Managed Heap
Commonly stores local value-type data and method call information. Stores objects and dynamically allocated managed data.
Memory is associated with method execution. Objects can remain alive beyond a single method call.
Not managed by the Garbage Collector in the same way as the managed heap. Managed by the .NET Garbage Collector.

Garbage Collection and IDisposable

Garbage Collection manages memory for managed objects, but not every resource used by an application is simply managed memory. Applications may also use external or unmanaged resources such as files, database connections, network resources, and streams.

For such resources, classes commonly implement IDisposable. The using statement helps ensure that the resource is disposed of properly.

C#
using ( var file = new StreamReader( "data.txt"))
{
    string content = file.ReadToEnd();
    Console.WriteLine( content);
}

The using statement ensures that the object is disposed when the block is completed, helping release the associated resource promptly.

Remember: Garbage Collection and resource disposal are related to application resource management, but they are not the same thing. GC manages managed memory, while IDisposable is used for deterministic cleanup of resources.

Finalizers in C#

A finalizer is a special method that can be used by a class to perform cleanup before an object is reclaimed by the Garbage Collector. Finalizers are mainly relevant when working with unmanaged resources.

C#
class Demo {
    ~Demo()
    {
         // Cleanup logic
    }
}
Best Practice: Do not use finalizers unnecessarily. When a type owns unmanaged resources, the recommended disposal pattern should generally be used instead of relying only on finalization.

Can Garbage Collection Prevent All Memory Leaks?

No. Garbage Collection can reclaim objects that are no longer reachable, but an object can remain reachable even when the application no longer logically needs it.

For example, keeping unnecessary objects in long-lived collections, event subscriptions, caches, or static references can cause memory usage to grow.

C#
static List< Student> students = new List< Student>();

If objects continue to be referenced by a long-lived collection, the Garbage Collector cannot simply collect those objects because they are still reachable.

Garbage Collection Best Practices

  • Allow the .NET runtime to manage normal managed memory.
  • Avoid calling GC.Collect() unnecessarily.
  • Dispose objects that implement IDisposable.
  • Prefer the using statement for disposable resources whenever appropriate.
  • Avoid keeping unnecessary objects in long-lived collections.
  • Be careful with static references and event subscriptions.
  • Understand object lifetime when designing applications.

Example 👨‍🏫❤️

Consider an e-commerce application. While processing a customer request, the application may create several temporary objects such as order details, calculations, response models, and temporary data.

Once those objects are no longer needed and there are no active references to them, they can become eligible for garbage collection. The .NET runtime can then reclaim their managed memory when appropriate.

CIIT Interview Points

  • What is Garbage Collection in C#?
  • What is a managed heap?
  • What is the difference between reachable and unreachable objects?
  • What are Generation 0, Generation 1, and Generation 2?
  • What is the purpose of GC.Collect()?
  • Why should GC.Collect() not be called unnecessarily?
  • What is IDisposable?
  • What is the purpose of the using statement?
  • Can Garbage Collection prevent every memory leak?

Common Beginner Mistakes

  • Thinking that null immediately deletes an object.
  • Calling GC.Collect() after every object creation.
  • Assuming Garbage Collection immediately releases all resources.
  • Forgetting to dispose objects that implement IDisposable.
  • Keeping unnecessary references in long-lived objects.

Summary

  • Garbage Collection is an automatic memory-management feature of .NET.
  • It works primarily with the managed heap.
  • Objects that are no longer reachable can become eligible for garbage collection.
  • .NET uses generations such as Gen 0, Gen 1, and Gen 2.
  • GC.Collect() can request collection, but normally should not be used unnecessarily.
  • Garbage Collection manages managed memory, while IDisposable helps with deterministic resource cleanup.
  • Good object lifetime and resource-management practices are important for building reliable applications.

Practice Questions

  1. Explain Garbage Collection in your own words.
  2. What is the managed heap?
  3. What makes an object eligible for Garbage Collection?
  4. Explain Generation 0, Generation 1, and Generation 2.
  5. Write a C# program that creates an object and then removes its reference.
  6. What does GC.Collect() do?
  7. Why should developers avoid unnecessary calls to GC.Collect()?
  8. Explain the difference between Garbage Collection and IDisposable.