Boxing unboxing in C#
C# has two kinds of data types, value types and reference types. Value type stores the value itself, whereas the reference type stores the address of the value where it is stored. Some predefined data types such as int, float, double, decimal, bool, char, etc. are value types and object, string, and array are reference types.
While working with these data types, you often need to convert value types to reference types or vice-versa. Because, both have different characteristics and .NET stores them differently in the memory, it must do some work internally to convert them from one type to another. These conversion processes are called boxing and unboxing.
What is boxing?
Boxing is the process of converting a value type to the object type or any interface type implemented by this value type. Boxing is implicit.
int i = 10;
object o = i; //performs boxing
In the above example, the integer variable i
is assigned to object o
. Since object type is a reference type and base class of all the classes in C#, an int can be assigned to an object type. This process of converting int to object is called boxing.
Let's look at a more practical example.
ArrayList list = new ArrayList();
list.Add(10); // boxing
list.Add("Bill");
Above, ArrayList is a class in C#, and so it is a reference type. We add an int value 10
in it. So, .NET will perform the boxing process here to assign value type to reference type.
Why named boxing?
You may be wondering, why is it named as boxing?
As you know, all the reference types stored on heap where it contains the address of the value and value type is just an actual value stored on the stack. Now, as shown in the first example, int i
is assigned to object o
. Object o
must be an address and not a value itself. So, the CLR boxes the value type by creating a new System.Object on the heap and wraps the value of i
in it and then assigns an address of that object to o
. So, because the CLR creates a box on the heap that stores the value, the whole process is called 'Boxing'.
The following figure illustrates the boxing process.
What is Unboxing?
Unboxing is the reverse of boxing. It is the process of converting a reference type to value type. Unboxing extract the value from the reference type and assign it to a value type.
Unboxing is explicit. It means we have to cast explicitly.
object o = 10;
int i = (int)o; //performs unboxing
The following figure illustrates the unboxing process.
A boxing conversion makes a copy of the value. So, changing the value of one variable will not impact others.
int i = 10;
object o = i; // boxing
o = 20;
Console.WriteLine(i); // output: 10
The casting of a boxed value is not permitted. The following will throw an exception.
int i = 10;
object o = i; // boxing
double d = (double)o; // runtime exception
First do unboxing and then do casting, as shown below.
int i = 10;
object o = i; // boxing
double d = (double)(int)o; // valid
Boxing and unboxing degrade the performance. So, avoid using it. Use generics to avoid boxing and unboxing. For example, use List<int>
instead of ArrayList
.
Read this interesting discussion on stackoverflow: Why do we need boxing and unboxing in C#?