Garbage Collection in C# | .NET Framework
Garbage collection is a memory management technique used in the .NET Framework and many other programming languages. In C#, the garbage collector is responsible for managing memory and automatically freeing up memory that the application is no longer using.
The garbage collector periodically scans the application’s memory to determine which objects are still being used and which are no longer needed. Objects that are no longer being used are marked for garbage collection, and their memory is freed up automatically by the garbage collector.
Key Features of Garbage Collector
- Automatic memory management: The garbage collector takes care of memory management automatically and helps to reduce the risk of memory leaks and other issues.
- Low impact on application performance: It runs in the background and has a low impact on application performance. In some cases, garbage collection can cause brief pauses or slowdowns in the application, particularly when large amounts of memory need to be freed up at once.
- Generation-based collection: Uses a generation-based approach to memory management. Objects are initially allocated in a “young” generation and are moved to an “old” generation if they survive multiple garbage collection cycles. This approach helps reduce the amount of time required for garbage collection, as most objects are collected by the young generation.
- Finalization: Provides support for finalization, A process that allows objects to perform cleanup tasks before they are destroyed. Objects with finalizers are moved to a separate finalization queue, processed by the garbage collector, and then other objects are collected.
Need for Garbage Collector
When a class object is created at runtime, a certain memory space is allocated to it in the heap memory. However, after all the actions related to the object are completed in the program, the memory space allocated to it is a waste as it cannot be used. In this case, garbage collection is very useful as it automatically releases the memory space after it is no longer required.
Garbage collection will always work on a Managed Heap, and internally, it has an Engine, which is known as the Optimization Engine.
Conditions to Trigger Garbage Collector
Garbage Collection occurs if at least one of multiple conditions is satisfied. These conditions are given as follows:
- Low Physical Memory: If the system has low physical memory, then garbage collection is necessary.
- Threshold Memory Exceeded: If the memory allocated to various objects in the heap memory exceeds a pre-set threshold, then garbage collection occurs.
- Manual Calling using Method: If the GC.Collect method is called, then garbage collection occurs. However, this method is only called under unusual situations as normally garbage collector runs automatically.
Phases in Garbage Collection
There are mainly 3 phases in garbage collection. Details about these are given as follows:
1. Marking Phase
A list of all the live objects is created during the marking phase. This is done by following the references from all the root objects. All of the objects that are not on the list of live objects are potentially deleted from the heap memory.
2. Relocating Phase
The references of all the objects that were on the list of all the live objects are updated in the relocating phase so that they point to the new location where the objects will be relocated to in the compacting phase.
3. Compacting Phase
The heap gets compacted in the compacting phase as the space occupied by the dead objects is released and the live objects remaining are moved. All the live objects that remain after the garbage collection are moved towards the older end of the heap memory in their original order.
Heap Generations in Garbage Collection
The heap memory is organized into 3 generations so that various objects with different lifetimes can be handled appropriately during garbage collection. The memory for each Generation will be given by the Common Language Runtime(CLR) depending on the project size. Internally, the Optimization Engine will call the Collection Means Method to select which objects will go into Generation 1 or Generation 2.

- Generation 0: All the short-lived objects such as temporary variables are contained in the generation 0 of the heap memory. All the newly allocated objects are also generation 0 objects implicitly unless they are large objects. In general, the frequency of garbage collection is the highest in generation 0.
- Generation 1: If space is occupied by some generation 0 objects that are not released in a garbage collection run, then these objects get moved to generation 1. The objects in this generation are a sort of buffer between the short-lived objects in Generation 0 and the long-lived objects in Generation 2.
- Generation 2: If space occupied by some generation 1 objects that are not released in the next garbage collection run, then these objects get moved to generation 2. The objects in generation 2 are long lived such as static objects as they remain in the heap memory for the whole process duration.
Notes:
- Garbage collection of a generation also includes its younger generations. Therefore, a collection of Generation 2 is a full garbage collection, releasing all objects in the heap.
- Memory allocated to Generation 2 is larger than Generation 1, and Generation 1 is larger than Generation 0 (Generation 2 > Generation 1 > Generation 0).
Example: Demonstration of heap generations in garbage collection to get the count of the number of Generations.
// Using MaxGeneration property of GC class
// to get the number of generations
using System;
public class Geeks
{
public static void Main(string[] args)
{
Console.WriteLine("The number of generations are: "
+ GC.MaxGeneration);
}
}
Output
The number of generations are: 1
Explanation: In the above example we use the the GC.MaxGeneration property of the GC class which returns the number of generations in the garbage collector. This property returns the generations that are supported by the system i.e. 2. If we run this program on online compilers then it may get different outputs as it depends on the system.
Methods of GC Class
The GC class controls the garbage collector of the system. Some of the methods in the GC class are given as follows:
1. GC.GetGeneration()
This method returns the generation number of the target object. It requires a single parameter i.e. the target object for which the generation number is required.
Syntax:
int GC.GetGeneration(Object obj);
- Parameters: It takes an object from which we want to retrieve the generation number
- Return Type: Returns an int value of the number of objects.
Example:
// Using GC.GetGeneration() Method
// To Get the Generation of the Object
using System;
public class Geeks
{
public static void Main(string[] args)
{
Geeks obj = new Geeks();
// Get the generation of the object
int c = GC.GetGeneration(obj);
Console.WriteLine("The generation of the object is: " + c);
}
}
Output
The generation of the object is: 0
2. GC.GetTotalMemory()
This method returns the number of bytes that are allocated in the system. It requires a single boolean parameter where true means that the method waits for the occurrence of garbage collection before returning and false means the opposite.
Syntax:
long GC.GetTotalMemory(bool forceFullCollection);
- Parameters: Takes a boolean value forceFullCollection If true, it forces a garbage collection to occur before reporting the memory usage.
- Return Type: It returns a long value of the total memory used in bytes.
Example:
// Using GC.TotalMemory() Method in C#
// To get the total memory allocated by the GC in bytes
using System;
public class Geeks
{
public static void Main(string[] args)
{
long memory = GC.GetTotalMemory(false);
Console.WriteLine("Total Memory:" + memory);
// Creating object of Geeks class
Geeks obj = new Geeks();
// Getting the generation number of object obj
int generation = GC.GetGeneration(obj);
// Displaying the generation number
Console.WriteLine("The generation number of object obj is: "
+ generation);
memory = GC.GetTotalMemory(false);
// Displaying the total memory allocated by the GC
Console.WriteLine("Total Memory:" + memory);
}
}
Output
Total Memory:4197120 The generation number of object obj is: 0 Total Memory:4207768
3. GC.Collect()
Garbage collection can be forced into the system using the GC.Collect() method. This method requires a single parameter i.e. number of the oldest generation for which garbage collection occurs.
Syntax:
void GC.Collect();
Example:
// Using GC.Collect() method to force garbage collection in Generation 0
using System;
public class Geeks
{
public static void Main(string[] args)
{
// Force garbage collection
// in Generation 0
GC.Collect(0);
// Get the current generation
// of garbage collection
int c = GC.CollectionCount(0);
Console.WriteLine(
"Garbage Collection in Generation 0 is: "
+ c);
}
}
Output
Garbage Collection in Generation 0 is: 1
4. GC.WaitForPendingFinalizers()
This method is used to block the current thread until all the finalizers have been executed. It ensures that any pending cleanup is completed before the continuation of the program.
Syntax:
void GC.WaitForPendingFinalizers();
Example:
// Using GC.WaitForPendingFinalizers() Method
// To Wait for Finalizers to Complete
using System;
public class Geeks
{
public static void Main(string[] args)
{
// Wait until all finalizers have been executed
GC.WaitForPendingFinalizers();
Console.WriteLine("Waiting for pending finalizers to complete.");
}
}
Output
Waiting for pending finalizers to complete.
Benefits of Garbage Collection
- Garbage Collection succeeds in allocating objects efficiently on the heap memory using the generations of garbage collection.
- Manual freeing of memory is not needed as garbage collection automatically releases the memory space after it is no longer required.
- Garbage collection handles memory allocation safely so that no object uses the contents of another object mistakenly.
- The constructors of newly created objects do not have to initialize all the data fields as garbage collection clears the memory of objects that were previously released.