Deep Dive Into Boxing And Unboxing

In this article you will learn about boxing, unboxing, memory organization, and CLR.

Memory Organization

To understand boxing and unboxing we should understand computer memory, how it works, and how C# compiler (.NET) uses computer memory to store data.

Operating Systems and CLR (Common Language Runtime) divides computer memory into two parts called stack and heap to work with data. All the value types are stored on stack and all the reference types are stored on heap. Both parts are managed in a distinct manner.

  • Whenever we call a method all the local variables are created on stack and when we call another method or return to the Main method all the acquired memory is released from the stack to reuse. This is done by the .NETGC (Garbage Collector) automatically. For example:

    Garbage Collector

    call a method

    Inside addCount method local variable Count is incremented by one. But in the main method count the variable has a value of 0 because after executing the addCount method all the memory taken by its local variable was released and no Count variable exists anymore.

    Stack

  • When we create an instance of any class (custom class or system class) it is created on heap. We use new keyword to create all the reference types. Its reference is stored on the stack that points to a specific location on the heap. We can create many objects as per requirement they all will point to the same location on heap. And when last reference is removed all the previous object references are also destroyed and the memory on heap is released (although this is not done immediately because like stack this is not done using .NET CG). That’s why heap is used for reusability whenever working with objects or reference types. For example:

    create an instance of any class

    run code

    Because array is a reference type when we call addValues method local variable array was not removed from memory both variables in main and in addValues method reference to the same memory location on the heap.

    array

Now we understand the memory organization. Let’s see the value types and reference types in .NET Framework.

System.Object class

In .NET framework all the value types and reference types are derived from System.Object class. This is the parent class which is derived by all the available data types in .NET Framework. That means all the data types are the specialized classes of System.Object class. All the available data types and their hierarchy in .NET Framework is as follows:

Object

Here all reference types are classes and value types are enumerations and structures.

Explicit and Implicit casting

When we work with data types there are situations when we need some sort of conversion to store any computational result. .NET Architecture allows type conversion among different primitive types. Sometimes it is quite possible that our result is too large or too small to store in the specific data type. Here Explicit or Implicit casting comes in handy.

Implicit Casting is done by the compiler. This is sometimes called Widening Data Type Conversion because we try to store the smaller result to the larger data type. For example:

Implicit Casting

run program

Variable marks is of int type, when we want to store the result in float type then some information is lost. But still compiler is doing implicit conversion for us. It is storing int result in the float data type.

Explicit Casting is done by the programmer. This is called Narrowing Data Type Conversion because some information may loss in the conversion, storing the large result to the smaller data types. For example:

Explicit Casting

see result

Here we are casting explicitly marks variable to float type so that we can get whole result after division.

Boxing and Unboxing

Although we can convert from one data type to another data type, .NET Architecture also allows us to convert form value type to reference type and conversely. For instant we can store int type to object type (Boxing) and object type to int type (Unboxing).

Boxing

As we know that Object is parent class for all the data types so it can refer to any reference and value type. Whenever we store a value type to a reference type (Object) what runtime does for us is, it create a memory on heap, copies the value of value type into that memory location, and stores the reference to that location on the stack. This is called Implicit Conversion.

chart

For example:

see program

see output

Here implicit cast is performed and int data type is converted to object, widening the age variable. But still it is Int32 structure. Because what is done by the runtime, a reference is created pointing to 10 in the heap.

Unboxing

Once we store the value type in the reference type we may want to use this value later in our application. We may attempt to cast back the object type to the value type. But we’ll get a compile time error. And it does make sense that int is a value type it can’t store a reference to a memory location. So we have to explicitly caste reference type to value type to get that value back. This is called Explicit Conversion.

Unboxing

For example:

program

Here we are storing a reference type in value type. But this will not compile and shows the following error.

error

Because Age is and object type. Here an explicit conversion is required and we have to cast Age back into int type.

explicit conversion

Now if we compile and run this code it will compile and shows following output.

result

Boxing is used when we want to compare two objects.

For example:
We have a Human class:

example

A Teacher class inheriting Human class:

Boxing

If we want to convert Teacher into object type we can use is operator to check if Teacher is an object type.

object type

run

We can also use as operator to cast a type to another type and check compatibility:

check compatibility

And we can cast back Object into Teacher object as follows:

cast back Object

This will produce following output:

output

Sometimes boxing is necessary (to check compatibility and equality of different objects) but we should avoid this because it involves a lot of overhead of creating a new memory location on heap copy value and then assign its reference on stack. It can slow down our application becausethe  processor has to do extra work of memory management and allocation. This delay can’t be noticed in small applications but when we work with large projects this can slow down application performance.

Read more articles on C# Programming: