C# - What does boxing and unboxing mean?

In this blogpost I will try to make a simple to understand description and example of boxing and unboxing.

In order to understand what boxing and unboxing is we need to understand our two kinds of types. In C# we have value types (struct, int, double, Guid etc.) and reference types (String, Object etc.). Reference types are a reference to a location in the memory that contains the actual data. A value type contains the data inside its own memory allocation. When passing on a reference type to a method you are just passing on the reference, whereas with a value type you are passing on a copy of the value.

Boxing and unboxing

Boxing is the action of converting a value type into a reference type. This happens by copying the value to the heap and creating a reference to it (the new object). An example of this is seen below:

int k = 1;
object kAsObject = k;  //Boxes the value type k in a reference type called kAsObject

Here our variable k is boxed in the variable kAsObject. My way of remembering this is that "we wrap (box) our value in a reference type". Unboxing is the exact opposite. We can easily unbox our previous made variable with the following piece of code:

int k2 = (int)kAsObject; // Unboxing kAsObject to k2.

That is simply put, boxing and unboxing.

But think, how often would you cast a simple type such as bool, int or double to an object? Probably not that often, which is why I believe few know about boxing and unboxing. To most developers, it is just a "typecast". However typecasts and boxing are two different things, but they share the same syntax. As mentioned boxing and unboxing is the conversion between reference and value types. On the other hand "Casting is when you convert a basic type to another basic type (like from an int to a long), or when you change the type of a reference (like from List<int> to IEnumerable<int>)" - stolen from stackoverflow.

Many developers do not think whether something is an implicit typecast or unboxing. Which is due to them looking the same. However take a look at the following:

int i = 23;
object k2 = i; //boxing
    
string s = "test";
object k1 = s; //cast

In the above example - is it not odd that you can cast an int to an object when it does not inherit from it or implement it? That's because it is not a typecast - it is boxing. However the string in the above actually does inherit from the object and can therefore be cast to that type. Same syntax, but something different happens

That's it!

This was my simplified explanation of boxing and unboxing. Let me know in the comments if I got anything wrong or if something was unclear :)