Garbage collection
One of the most important features of CLR is the garbage collector. Since the .NET Core applications are managed applications, most of the garbage collection is done automatically by the CLR. The allocation of objects in the memory is efficiently done by the CLR. The CLR not only tunes the virtual memory resources from time to time, but it also reduces the fragmentation of underlying virtual memory to make it more efficient in terms of space.
When the program is run, the objects start allocating memory on the heap and each object's address is stored on the stack. This process continues until the memory reaches its maximum limit. Then the GC comes into play and starts reclaiming memory by removing the unused managed objects and allocating new objects. This is all done automatically by the GC, but there is also a way to invoke the GC to perform garbage collection by calling the GC.Collect method
Let's take an example where we have a Car object called c in the Main method. When the function is executed, the Car object will be allocated by the CLR into the heap memory and the reference to that c object will be stored in the stack address pointing to the Car object on the heap. When the garbage collector runs, it reclaims the memory from the heap and removes the reference from the stack:
Some important points to note are that the garbage collection is done automatically by the GC on managed objects, and that if there are any unmanaged objects, such as database connections, I/O operations, and so on, they need to be garbage collected explicitly. Otherwise, GC works efficiently on managed objects and ensures that the application will not experience any decrease in performance when the GC is performed.