Hello! Welcome to your first lesson in mastering the C# programming language.
Given your experience with ASP.NET and your goal to understand the "under the hood" mechanics of C#, we're going to start with a concept that is absolutely fundamental to writing high-performance and correct C# code: the distinction between different types of data and where they live in memory.
This lesson directly addresses the learning outcome: Distinguish value types (struct, enum) from reference types (class, delegate, interface) in C# and explain their memory allocation differences (stack vs. heap).
Understanding this is not just an academic exercise. It impacts everything from performance and memory usage to the subtle bugs that can arise when passing data between methods. While Java also distinguishes between primitive and object types, you'll find that C#'s struct keyword gives developers a powerful tool to create custom, high-performance value types, making this topic even more crucial.
Let's begin.
1. The Memory Landscape: Stack and Heap
Every C# program operates using two primary regions of memory: the stack and the heap. Understanding their distinct roles and characteristics is the first step.
- The Stack is a highly efficient, LIFO (Last-In, First-Out) data structure. Think of it as a stack of plates: you add new plates to the top and remove them from the top. It's used for short-lived data, such as local variables within a method and parameters passed to it. Allocation and deallocation are extremely fast because they just involve adjusting a single pointer.
- The Heap is a large pool of memory used for data that needs to live longer than a single method call. This is where "objects" reside. Allocating memory on the heap is more complex, and cleaning it up is the job of the Garbage Collector (GC).
To get a detailed visual explanation of how this works, please watch the first few segments of the following video. It provides an excellent foundation.
Inside C#: Stack & Heap, Value Types, Boxing, stackalloc + More
This video, from the channel ABMedia, provides a fantastic deep dive into C#'s memory model. We'll start with the sections explaining the stack and the heap.
Please watch from the timestamp 01:10 to 10:23. Focus on: The core purpose and operational model of the stack (pushing/popping with function calls). The role of the heap as a memory pool for objects. The introduction to the Garbage Collector's function.
To summarize the key points from the video:
- Stack: Fast, ordered, small, and its lifetime is tied to the scope of your methods.
- Heap: Slower, unordered, large, and its lifetime is managed by the GC, allowing data to persist across method calls.
For a concise textual reference that reinforces these concepts, the article "Understanding the Stack and Heap in C#" is very helpful.
Understanding the Stack and Heap in C# | endjin
This article from endjin clearly defines the stack and heap and their roles in C#.
Please read the first two sections, titled 'What is "the stack"?' and 'What is "the heap"?'. This will solidify the concepts introduced in the video.
2. C#'s Type System: Value vs. Reference Types
Now that we have our memory landscape, let's see how C# types fit into it. Every type in C# falls into one of two main categories: value types or reference types.

- Value Types: Variables of these types directly contain their data. The fundamental building blocks are
structandenum. This category includes all numeric types (int,float,double),char, andbool. - Reference Types: Variables of these types store a reference (think of it as a memory address or a pointer) to their data, which is located elsewhere. The core reference type is the
class.interface,delegate, andstringare also reference types.
This distinction dictates how types behave in memory. The following video sections explain this crucial difference in detail.
Inside C#: Stack & Heap, Value Types, Boxing, stackalloc + More
Let's continue with the 'Inside C#' video to see how value and reference types are handled in memory.
Please watch from 10:23 to 20:52. Pay close attention to: The single, unbreakable rule for reference types (allocation on the heap). The simpler rule for value types (contents placed directly where they are). The visual examples of how classes and structs are laid out in memory.
3. Where Are They Stored? The Rules of Memory Allocation
A common oversimplification is "value types go on the stack, reference types go on the heap." The reality is more nuanced and more powerful. The endjin article provides a perfect, clear set of rules.
Understanding the Stack and Heap in C# | endjin
This section of the endjin article is one of the clearest explanations available for where C# variables are stored. It corrects common misconceptions.
Please read the section titled 'So where do C# variables get stored?'. The bullet points here are the key takeaways for this entire lesson.
Here is a summary of those essential rules:
- A local variable (declared inside a method) always lives on the stack.
- If it's a value type (e.g.,
int x = 10;), its value (10) is on the stack. - If it's a reference type (e.g.,
MyClass c = new MyClass();), the reference to the object is on the stack.
- If it's a value type (e.g.,
- The object itself (the instance created with
new MyClass()) always lives on the heap. - An instance variable (a field) of a class lives where its containing object lives: on the heap. This is true even if the field is a value type. For example, if
MyClasshas anintfield, thatintlives inside theMyClassobject on the heap. - An instance variable of a struct lives where its containing struct lives. If the struct is a local variable, its fields live on the stack. If the struct is a field within a class, its fields live on the heap, embedded inside the class object.
4. The Consequences: Assignment, Method Passing, and Performance
This memory model has profound consequences for how you write code.
Assignment and Method Arguments
When you assign one variable to another or pass one as a method argument, what gets copied depends on its type.
- Value Types are copied by value: The entire data is duplicated.
- Reference Types are copied by reference: Only the memory address is duplicated. Both variables end up pointing to the same object on the heap.
The "Value vs Reference Types in C#" article provides clear code examples of this behavior.
Value vs Reference Types in C# - In Depth Guide - Code Maze
This article from Code Maze demonstrates the practical differences in assignment and method passing with clear code examples.
Read the sections 'Value Type Assignment', 'Reference Type Assignment', and 'Value and Reference Types as Method Arguments'. Notice how changing a copied reference type affects the original, while changing a copied value type does not.
This diagram perfectly illustrates what happens when you pass a reference type to a method. The testCar variable in Main and the car parameter in IncreaseCarPrice are two separate variables on the stack, but they both hold a copy of the same reference, pointing to the single Car object on the heap.

Performance Implications
This is where your goal of understanding "under the hood" really pays off. The choice between a class and a struct is a performance decision.
To see a detailed breakdown with benchmarks, the final video section for this lesson is invaluable. It directly addresses why reference types are so common despite the performance benefits of value types.
Inside C#: Stack & Heap, Value Types, Boxing, stackalloc + More
We'll conclude with a deep dive into the performance trade-offs. This section of the 'Inside C#' video is packed with insights relevant to high-performance coding.
Please watch from 20:52 to 36:28. This is a longer segment, but it's crucial. It covers: The performance cost of heap allocations and garbage collection. The benefit of cache locality when using arrays of structs. The cost of 'indirection' (following references). The downsides of structs, particularly the cost of copying large ones.
Key Performance Takeaways:
- Structs (Value Types) can be significantly faster when used correctly (e.g., in large arrays) because they avoid heap allocation overhead and improve CPU cache performance by keeping data contiguous in memory.
- Classes (Reference Types) introduce costs: heap allocation, garbage collection pressure, and CPU cache misses due to data being scattered across the heap (indirection). However, they are flexible, support inheritance, and avoid the cost of copying large data structures—you only copy an 8-byte reference.
Conclusion
You've just covered one of the most important foundational concepts in C#. A solid grasp of this topic separates proficient developers from true experts.
Here are the key takeaways from this lesson:
- C# uses two main memory areas: the stack for fast, temporary, scoped data, and the heap for longer-lived objects managed by the Garbage Collector.
- Types are either value types (
struct,enum, primitives) which hold their data directly, or reference types (class,interface,delegate) which hold a reference to data on the heap. - Where a variable is stored depends on its type and its declaration context. A value type can live on the heap if it's part of a class.
- This distinction critically affects performance, memory usage, and how data behaves when passed between methods.
Preview of the Next Lesson:
We've established a clear line between value and reference types. But what happens when you need to treat a value type as if it were a reference type, for example, by adding it to a list of generic objects? This leads to a process called boxing, which has its own performance implications. In our next lesson, we will explore boxing and unboxing in detail.