<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexey Popov</title>
    <description>The latest articles on DEV Community by Alexey Popov (@alexey_popov).</description>
    <link>https://dev.to/alexey_popov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4083826%2Fd51b5f95-52ad-4fed-9ca7-9342077b55e6.jpg</url>
      <title>DEV Community: Alexey Popov</title>
      <link>https://dev.to/alexey_popov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexey_popov"/>
    <language>en</language>
    <item>
      <title>Understanding Memory in .NET</title>
      <dc:creator>Alexey Popov</dc:creator>
      <pubDate>Thu, 03 Sep 2026 15:08:16 +0000</pubDate>
      <link>https://dev.to/alexey_popov/understanding-memory-in-net-4pcc</link>
      <guid>https://dev.to/alexey_popov/understanding-memory-in-net-4pcc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With the rise of large language models (LLMs), the distinction between &lt;em&gt;writing code&lt;/em&gt; and &lt;em&gt;programming&lt;/em&gt; has become more apparent than ever.&lt;/p&gt;

&lt;p&gt;To an LLM, source code is merely text. To a computer, it is a sequence of instructions. A developer’s task is to understand what actually happens when those instructions are executed.&lt;/p&gt;

&lt;p&gt;This is why studying a programming language often begins not with syntax, but with the program’s execution model. One of the most important parts of that model is memory: how data is represented, how it is copied, how long it remains alive, and how different pieces of data interact while a program is running.&lt;/p&gt;

&lt;p&gt;In this article, we will explore two primary memory regions used by .NET applications, why they serve different purposes, and how this design influences both the behavior and performance of .NET applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Regions
&lt;/h2&gt;

&lt;p&gt;When a .NET application starts, the operating system creates a process and its first execution thread (&lt;em&gt;primary thread&lt;/em&gt;). The &lt;strong&gt;Common Language Runtime (CLR)&lt;/strong&gt; is then initialized and takes responsibility for executing the application, including managing the &lt;strong&gt;Managed Heap&lt;/strong&gt; and the &lt;strong&gt;Garbage Collector&lt;/strong&gt; [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading" rel="noopener noreferrer"&gt;1&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;During execution, additional threads may be created by the application or used by the runtime. Each thread has its own &lt;strong&gt;Stack&lt;/strong&gt; and CPU register state [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading" rel="noopener noreferrer"&gt;1&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;As a result, a running .NET application relies on two primary memory regions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stack&lt;/strong&gt; - private to each thread and used for method execution and local state [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading" rel="noopener noreferrer"&gt;1&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Heap&lt;/strong&gt; - shared by threads in the process and managed by the CLR's Garbage Collector [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But why does the platform need two different memory regions?&lt;/p&gt;

&lt;p&gt;Because different kinds of data have different requirements regarding access speed, lifetime, and storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Representation
&lt;/h2&gt;

&lt;p&gt;In .NET, there are two fundamental ways of representing data: &lt;strong&gt;Value Types&lt;/strong&gt; and &lt;strong&gt;Reference Types&lt;/strong&gt; [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system" rel="noopener noreferrer"&gt;3&lt;/a&gt;].&lt;/p&gt;

&lt;h3&gt;
  
  
  Value Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Value Types&lt;/strong&gt; are used when only the value itself matters.&lt;/p&gt;

&lt;p&gt;Consider a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the assignment, the program contains two independent copies of the value. Changing one variable has no effect on the other because each variable stores its own value [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system" rel="noopener noreferrer"&gt;3&lt;/a&gt;]:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvnuthprtfbchqjary8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnvnuthprtfbchqjary8v.png" alt="Figure 1" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. Assigning a Value Type creates an independent copy of the value&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;From the CLR’s perspective, such data does not need a distinct identity because only the value matters. Its exact storage location is therefore determined entirely by the context in which it is used.&lt;/p&gt;

&lt;p&gt;This is why small, independent pieces of data (numbers, coordinates, dates, dimensions, or colors) are commonly represented as &lt;strong&gt;Value Types&lt;/strong&gt; in .NET.&lt;/p&gt;

&lt;p&gt;For example, an application may store the coordinates of millions of points on a map or the vertices of a three-dimensional model. Each point is merely a set of numbers. Copying such values is a natural process and does not require the creation of separate objects with their own identities.&lt;/p&gt;
&lt;h3&gt;
  
  
  Reference Types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reference Types&lt;/strong&gt;, by contrast, are used when not only the information matters, but also the identity of the entity to which that information belongs.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;user2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the &lt;code&gt;user1&lt;/code&gt; and &lt;code&gt;user2&lt;/code&gt; assignments, both variables refer to the same object [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system" rel="noopener noreferrer"&gt;3&lt;/a&gt;]:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftcwt4d8b0imyy1ko2813.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftcwt4d8b0imyy1ko2813.png" alt="Figure 2" width="751" height="797"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2. Assigning a Reference Type copies the reference, not the object&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Such an object may be passed between methods, returned from them, stored in collections, and remain alive far longer than any individual method call. Its lifetime must therefore not depend on a particular stack frame. Instances of &lt;strong&gt;Reference Types&lt;/strong&gt; are allocated on the &lt;strong&gt;Managed Heap&lt;/strong&gt; [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference Types&lt;/strong&gt; are therefore well suited to modeling entities shared by multiple parts of a program. An object of &lt;code&gt;User&lt;/code&gt; class, for example, may be displayed in the user interface, stored in a collection, passed to a service, and used by an authentication system. All of these components must work with the same object instance rather than with independent copies.&lt;/p&gt;

&lt;p&gt;The same principle underlies most dynamic data structures. A linked list, for instance, consists of nodes, each of which stores a reference to the next node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference semantics make this representation natural: nodes can be connected and rearranged by changing references without copying the nodes themselves.&lt;/p&gt;

&lt;p&gt;Choosing between &lt;strong&gt;Value Types&lt;/strong&gt; and &lt;strong&gt;Reference Types&lt;/strong&gt; is therefore not primarily a matter of performance or coding style - it is a matter of modeling data correctly. As a general modeling principle, &lt;strong&gt;Value Types&lt;/strong&gt; are well suited to independent values, while &lt;strong&gt;Reference Types&lt;/strong&gt; are well suited to entities whose identity and shared state matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boxing and Unboxing
&lt;/h2&gt;

&lt;p&gt;.NET is built around an unified type system whose root is &lt;code&gt;System.Object&lt;/code&gt; [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system" rel="noopener noreferrer"&gt;3&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;As a result, a value of any type can be treated as an object when necessary [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Today&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;string&lt;/code&gt; is already a &lt;strong&gt;Reference Type&lt;/strong&gt;, but &lt;code&gt;42&lt;/code&gt; and &lt;code&gt;DateTime.Today&lt;/code&gt; are &lt;strong&gt;Value Types&lt;/strong&gt;. So how can they all be stored in the same collection?&lt;/p&gt;

&lt;h3&gt;
  
  
  Boxing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Boxing&lt;/strong&gt; is the implicit conversion of a &lt;strong&gt;Value Type&lt;/strong&gt; to &lt;code&gt;object&lt;/code&gt; or to an interface implemented by that type [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During boxing, the CLR [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;]:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allocates memory on the &lt;strong&gt;Managed Heap&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Creates a new object.&lt;/li&gt;
&lt;li&gt;Copies the value into that object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftsc4e4vcqa5grqigyua8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftsc4e4vcqa5grqigyua8.png" alt="Figure 3" width="799" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3. Boxing creates a new object on the Managed Heap containing a copy of the value&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Boxing &lt;strong&gt;does not move&lt;/strong&gt; a value from the &lt;strong&gt;Stack&lt;/strong&gt; to the &lt;strong&gt;Managed Heap&lt;/strong&gt;. Instead, the CLR allocates a new object on the heap and copies the value into it [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;]. The original value remains independent of the boxed copy.&lt;/p&gt;

&lt;p&gt;Every boxing operation therefore creates an additional heap object. Although allocating memory on the Managed Heap is generally fast, repeated boxing creates additional allocations and can increase the amount of work the &lt;strong&gt;Garbage Collector&lt;/strong&gt; must eventually perform [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;].&lt;/p&gt;

&lt;h3&gt;
  
  
  Unboxing
&lt;/h3&gt;

&lt;p&gt;After boxing, the value is represented as an &lt;code&gt;object&lt;/code&gt;. To use it again as an &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;DateTime&lt;/code&gt;, or any other &lt;strong&gt;Value Type&lt;/strong&gt;, it must first be &lt;strong&gt;unboxed&lt;/strong&gt; [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During unboxing, the CLR [&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;4&lt;/a&gt;]:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifies that the object contains a value of the expected type.&lt;/li&gt;
&lt;li&gt;Copies that value into a new variable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fscu2rzvzz860xep0blrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fscu2rzvzz860xep0blrb.png" alt="Figure 4" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4. Unboxing copies the value from the boxed object into a new Value Type variable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The boxed object itself remains on the &lt;strong&gt;Managed Heap&lt;/strong&gt; until it eventually becomes unreachable, and its memory can be reclaimed by the &lt;strong&gt;Garbage Collector&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Garbage Collector
&lt;/h2&gt;

&lt;p&gt;As long as an object exists on the &lt;strong&gt;Managed Heap&lt;/strong&gt;, the CLR must eventually determine when its memory can be reclaimed. This responsibility belongs to the &lt;strong&gt;Garbage Collector&lt;/strong&gt;, which serves as .NET's automatic memory manager [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;When a garbage collection is triggered, the &lt;strong&gt;Garbage Collector&lt;/strong&gt; examines the object graph starting from a set of &lt;strong&gt;Garbage Collector Roots&lt;/strong&gt;, determining which objects are still reachable. Objects that cannot be reached from these roots are considered garbage and their memory can be reclaimed [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Allocating objects on the managed heap is generally very fast because, while space is available, allocation primarily involves advancing a pointer [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;]. However, increasing the number and rate of heap allocations increases the amount of work the &lt;strong&gt;Garbage Collector&lt;/strong&gt; may need to perform.&lt;/p&gt;

&lt;p&gt;Moreover, if an object remains reachable - for example, through a static field or a collection - the GC considers it alive and will not reclaim its memory. Keeping references to objects that are no longer logically needed can therefore cause memory leaks even in managed applications [&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;2&lt;/a&gt;].&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Looking at the complete picture, it becomes clear that these mechanisms are not isolated features but parts of a single execution model.&lt;/p&gt;

&lt;p&gt;Understanding this model allows us to see .NET not as a collection of unrelated features, but as a coherent system whose components naturally build upon one another. This is why understanding the memory model forms the foundation for understanding many other parts of the modern .NET platform, including &lt;code&gt;Span&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;stackalloc&lt;/code&gt;, &lt;code&gt;async/await&lt;/code&gt;, &lt;code&gt;yield&lt;/code&gt;, and many others.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading" rel="noopener noreferrer"&gt;Microsoft Learn - Threads and threading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals" rel="noopener noreferrer"&gt;Microsoft Learn - Fundamentals of garbage collection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/base-types/common-type-system" rel="noopener noreferrer"&gt;Microsoft Learn - Common type system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing" rel="noopener noreferrer"&gt;Microsoft Learn - Boxing and Unboxing&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>dotnet</category>
      <category>beginners</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
