Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing

Leave a comment


Table of contents

This video explains the concept of boxing and unboxing and it also shows the performance implications caused by the same.


This article will explain six important concepts: stack, heap, value types, reference types, boxing, and unboxing. This article starts explaining what happens internally when you declare a variable and then it moves ahead to explain two important concepts: stack and heap. The article then talks about reference types and value types and clarifies some of the important fundamentals around them.

The article concludes by demonstrating how performance is hampered due to boxing and unboxing, with a sample code.

Watch my 500 videos on various topics like design patterns, WCF, WWF, WPF, LINQ, Silverlight, UML, SharePoint, Azure, VSTS, and a lot more: click here. You can also catch me on my trainings here.

What goes inside when you declare a variable?

When you declare a variable in a .NET application, it allocates some chunk of memory in the RAM. This memory has three things: the name of the variable, the data type of the variable, and the value of the variable.

That was a simple explanation of what happens in the memory, but depending on the data type, your variable is allocated that type of memory. There are two types of memory allocation: stack memory and heap memory. In the coming sections, we will try to understand these two types of memory in more detail.

Stack and heap

In order to understand stack and heap, let’s understand what actually happens in the below code internally.

public void Method1()
    // Line 1
    int i=4;

    // Line 2
    int y=2;

    //Line 3
    class1 cls1 = new class1();

It’s a three line code, let’s understand line by line how things execute internally.

    • Line 1: When this line is executed, the compiler allocates a small amount of memory in the stack. The stack is responsible for keeping track of the running memory needed in your application.
    • Line 2: Now the execution moves to the next step. As the name says stack, it stacks this memory allocation on top of the first memory allocation. You can think about stack as a series of compartments or boxes put on top of each other.

Memory allocation and de-allocation is done using LIFO (Last In First Out) logic. In other words memory is allocated and de-allocated at only one end of the memory, i.e., top of the stack.

  • Line 3: In line 3, we have created an object. When this line is executed it creates a pointer on the stack and the actual object is stored in a different type of memory location called ‘Heap’. ‘Heap’ does not track running memory, it’s just a pile of objects which can be reached at any moment of time. Heap is used for dynamic memory allocation.

One more important point to note here is reference pointers are allocated on stack. The statement, Class1 cls1; does not allocate memory for an instance of Class1, it only allocates a stack variable cls1 (and sets it to null). The time it hits the new keyword, it allocates on “heap”.

Exiting the method (the fun): Now finally the execution control starts exiting the method. When it passes the end control, it clears all the memory variables which are assigned on stack. In other words all variables which are related to int data type are de-allocated in ‘LIFO’ fashion from the stack.

The big catch – It did not de-allocate the heap memory. This memory will be later de-allocated by the garbage collector.

Now many of our developer friends must be wondering why two types of memory, can’t we just allocate everything on just one memory type and we are done?

If you look closely, primitive data types are not complex, they hold single values like ‘int i = 0’. Object data types are complex, they reference other objects or other primitive data types. In other words, they hold reference to other multiple values and each one of them must be stored in memory. Object types need dynamic memory while primitive ones needs static type memory. If the requirement is of dynamic memory, it’s allocated on the heap or else it goes on a stack.

Image taken from

Value types and reference types

Now that we have understood the concept of Stack and Heap, it’s time to understand the concept of value types and reference types. Value types are types which hold both data and memory on the same location. A reference type has a pointer which points to the memory location.

Below is a simple integer data type with name i whose value is assigned to another integer data type with name j. Both these memory values are allocated on the stack.

When we assign the int value to the other int value, it creates a completely different copy. In other words, if you change either of them, the other does not change. These kinds of data types are called as ‘Value types’.

When we create an object and when we assign an object to another object, they both point to the same memory location as shown in the below code snippet. So when we assign obj to obj1, they both point to the same memory location.

In other words if we change one of them, the other object is also affected; this is termed as ‘Reference types’.

So which data types are ref types and which are value types?

In .NET depending on the data type, the variable is either assigned on the stack or on the heap. ‘String’ and ‘Objects’ are reference types, and any other .NET primitive data types are assigned on the stack. The figure below explains the same in a more detail manner.

Boxing and unboxing

Wow, you have given so much knowledge, so what’s the use of it in actual programming? One of the biggest implications is to understand the performance hit which is incurred due to data moving from stack to heap and vice versa.

Consider the below code snippet. When we move a value type to reference type, data is moved from the stack to the heap. When we move a reference type to a value type, the data is moved from the heap to the stack.

This movement of data from the heap to stack and vice-versa creates a performance hit.

When the data moves from value types to reference types, it is termed ‘Boxing’ and the reverse is termed ‘UnBoxing’.

If you compile the above code and see the same in ILDASM, you can see in the IL code how ‘boxing’ and ‘unboxing’ looks. The figure below demonstrates the same.

Performance implication of boxing and unboxing

In order to see how the performance is impacted, we ran the below two functions 10,000 times. One function has boxing and the other function is simple. We used a stop watch object to monitor the time taken.

The boxing function was executed in 3542 ms while without boxing, the code was executed in 2477 ms. In other words try to avoid boxing and unboxing. In a project where you need boxing and unboxing, use it when it’s absolutely necessary.

With this article, sample code is attached which demonstrates this performance implication.

Currently I have not included source code for unboxing but the same holds true for it. You can write code and experiment it using the stopwatch class.

Source code

Attached with the article is a simple code which demonstrates how boxing creates performance implications. You can download the source code here.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


C# Terminology

Leave a comment


[This documentation is for preview only, and is subject to change in later releases. Blank topics are included as placeholders.]

access modifier
A keyword, such as private, protected, internal, or public, that restricts access to a type or type member. For more information, see Access Modifiers.

accessible member
A member that can be accessed by a given type. An accessible member for one type is not necessarily accessible to another type. For more information, see Access Modifiers and Friend Assemblies.

A method that sets or retrieves the value of a private data member value that is associated with a property. Read-write properties have get and set accessors. Properties that are read-only have only a get accessor. For more information, seeProperties.

anonymous method
An anonymous method is a code block that is passed as a parameter to a delegate. For more information, see Anonymous Methods.

base class
A class that is inherited by another ‘derived’ class. For more information, see Inheritance.

call stack
The series of method calls leading from the beginning of the program to the statement currently being executed at run time.

A data type that describes an object. Classes contain both data, and the methods for acting on the data. For more information, see Classes.

A special method on a class or struct that initializes the objects of that type. For more information, see Constructors.

A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. For more information, see Delegates.

derived class
A class that uses inheritance to gain, augment, or modify the behavior and data of another ‘base’ class. For more information, see Inheritance.

A special method on a class or struct that prepares the instance for destruction by the system. For more information, seeDestructors.

A member of a class or struct that sends notifications of a change. For more information, see Events.

A data member of a class or struct that is accessed directly.

Generics allow you to define a class and or method that are defined with a type parameter. When client code instantiates the type, it specifies a particular type as an argument. For more information, see Generics.

Integrated Development Environment. The application that provides the unified user interface for the various development tools including the compiler, debugger, code editor, and designers.

immutable type
A type whose instance data, fields and properties, does not change after the instance is created. Most value types are immutable.

inaccessible member
A member that cannot be accessed by a given type. An inaccessible member for one type is not necessarily inaccessible to another type. For more information, see Access Modifiers.

C# supports inheritance, so a class that derives from another class, known as the base class, inherits the same methods and properties. Inheritance involves base classes and derived classes. For more information, see Inheritance.

A type that contains only the signatures of public methods, events, and delegates. An object that inherits the interface must implement all of the methods and events defined in the interface. Classes or structs may inherit any number of interfaces. For more information, see Interfaces

An iterator is a method that enables consumers of a class that contains a collection or array to use foreach, in (C# Reference) to iterate through that collection or array.

A field, property, method, or event declared on a class or struct.

A named code block that provides behavior for a class or struct.

mutable type
A type whose instance data, fields and properties, can be changed after the instance is created. Most Reference Types are mutable.

nested type
A type declared within the declaration of another type.

An instance of a class. An object exists in memory, and has data and methods that act on the data. For more information, see Objects, Classes, and Structs.

A data member accessed by means of an accessor. For more information, see Properties.

Reusing previously entered code. The Visual C# Express Code Editor can intelligently reformat code to, for example, turn a block of highlight code into a method. For more information, see Refactoring.

reference type
A data type. A variable declared as a reference type points to a location where data is stored. For more information, seeReference Types.

A class or method declared as static exists without first being instantiated using the keyword new. Main() is a static method. For more information, see Static Classes and Static Class Members.

A compound data type that is typically used to contain a few variables that have some logical relationship. Structs can also contain methods and events. Structs do not support inheritance but they do support interfaces. A struct is a value type, while a class is a reference type. For more information, see Structs.

value type
A value type is a data type that is allocated on the stack, as opposed to a reference type which is allocated on the heap. The built-In types, including the numeric types as well as the struct type and the nullable type, are all value types. Theclass type and string type are reference types. For more information, see Value Types (C# Reference).


Other Resources