Boxing and Unboxing

Understanding .Net Boxing and Unboxing resource

Eduardo Silva
4 min readJul 5, 2023

Introduction

In the world of .NET C# Core, developers often encounter the terms “box” and “unboxing.” These concepts play a crucial role in handling value types and reference types. Understanding how box and unboxing work is essential for writing efficient and error-free code. In this blog post, we’ll delve into the concepts of box and unboxing, explore their significance, and provide practical examples to help you grasp these concepts effectively.

Photo by Mediamodifier on Unsplash

Heap and Stack in .NET

To understand the memory allocation in .NET, we need to explore the concepts of the heap and the stack.

The Heap: is a region of memory used for dynamic memory allocation. It is where objects and reference types are allocated. When an object is created using the “new” keyword, memory is allocated on the heap to store that object. The heap is managed by the garbage collector, which automatically deallocates memory when objects are no longer referenced.

// Reference type variables
string myString = "Hello";
var obj = new MyClass();

The Stack: The stack is a region of memory used for static memory allocation and managing method calls. It stores value types and reference types’ variables, along with method calls, parameters, and local variables. Each time a method is called, a new stack frame is created, which contains information specific to that method, including the method’s parameters and local variables. When the method execution is completed, the stack frame is popped off the stack.

int myNumber = 42; // Value type variable

That is a simplification. Not always a value type is stored in the stack (i.e., value type as attributes/properties in a object). If you want to learn more and understand the exceptions about type and references location in memory I recommend The Truth About Value Types.

Boxing in .NET

Boxing is the process of converting a value type into an object type (reference type). In other words, when a value type is boxed, it is wrapped inside an instance of the System.Object class. This enables the value type to be treated as an object, allowing it to be stored in collections such as ArrayList, Hashtable, or passed as a parameter to methods that accept objects.

Boxing is an implicit operation that occurs automatically when assigning a value type to an object type variable. For example:

int myNumber = 42;
object boxedNumber = myNumber; // Boxing occurs implicitly

In the above code snippet, the value of the integer variable myNumber is automatically boxed into an instance of the Object class when it is assigned to the boxedNumber variable. This boxing operation comes with a performance cost, as it involves allocating memory on the heap to store the boxed value type.

Unboxing in .NET

Unboxing is the reverse process of boxing. It involves extracting the value type from the boxed object and assigning it to a value type variable. Unboxing is an explicit operation and requires a cast to the appropriate value type.

object boxedNumber = 42; // Boxed integer
int unboxedNumber = (int)boxedNumber; // Unboxing occurs explicitly

In the above code snippet, the boxed integer boxedNumber is unboxed by casting it to the int type. It is crucial to note that unboxing can only be performed if the type of the boxed object matches the target value type; otherwise, an InvalidCastException will be thrown at runtime.

Performance Implications

Boxing and unboxing operations come at a performance cost, especially when performed frequently. Each boxing operation involves heap allocation, which can impact the overall performance of your application. Unboxing also incurs the overhead of casting the object back to its original value type.

To minimize the performance impact of boxing and unboxing, it is advisable to avoid them whenever possible, especially in performance-sensitive scenarios. Instead, consider using generic collections, such as List<T> or Dictionary<TKey, TValue>, that work directly with value types and eliminate the need for boxing and unboxing.

Practical Examples: Let’s consider a scenario where we want to store a collection of integers in a list. We can use a generic list to avoid boxing:

List<int> numbers = new List<int>();
numbers.Add(42); // No boxing occurs

In this example, the List<T> class is used with the int type, which is a value type. Thus, no boxing takes place when adding integers to the list.

On the other hand, if we were to use a non-generic collection, such as ArrayList, boxing would occur:

ArrayList nonGenericList = new ArrayList();
nonGenericList.Add(42); // Boxing occurs

In this case, since ArrayList is a collection that works with objects, the integer value 42 is boxed before being added to the list.

Conclusion

Understanding box and unboxing is crucial when working with value types and reference types in .NET C# Core. Boxing allows value types to be treated as objects, while unboxing extracts the value type from a boxed object. It is essential to be mindful of the performance implications of boxing and unboxing, as frequent usage can impact the performance of your applications.

--

--