Introduction To Boxing And Unboxing In C#

Introduction

 
In C#, each type of data is defined as a part of the programming language and all the variables used in our program must be defined with one of these data types. So, C# is a strongly typed programming language. The data types in C# is mainly of three types,
  1. Value Data Type
    The Value Data Types in C# will preserve the variable value directly in memory and support both signed and unsigned literals. There are mainly five types of Value Data Types in C#. They are: Signed and Unsigned Integral Types, Floating-Point Types, Decimal Types, Character Types, and Boolean Types.

  2. Reference Data Type
    These data types do not store the variable value directly in memory but contain a memory address of the variable value. String, Objects are the built-in reference data types.

  3. Pointer Data Type
    These data types store a memory address of the variable value. We use the ampersand (&) and the asterisk (*) operators to retrieve the data. The (&) operator determines the address of a variable while the (*) operator determines the value of an address.
C# allows converting a Value Type to a Reference Type and vice-versa. This is done through boxing and unboxing respectively. Boxing and Unboxing provide a single view of the type system, allowing every type attribute to be viewed as an object.
 

What is Boxing in C#?

 
Definition
 
It is the process of converting a Value Data Type to a Reference Data Type. This process is an implicit conversion and an object type is used. It consists of allocating an object instance and copying the Value Type value into that instance.
 
Syntax
  1. dataType varName;  
  2. Object objectName = varName;  
Here, varName is the name of the variable which is to be boxed into. objectName is the name of the object instance into which the variable will be boxed.

Example
 
Let us consider the following code,
  1. using System;  
  2. class Sample {  
  3.   static void Main() {  
  4.     int x = 100;  
  5.     object obj = x; // Boxing x into obj  
  6.     System.Console.WriteLine("Before changing the value of x :");  
  7.     System.Console.WriteLine("The value of x is : {0}", x);  
  8.     System.Console.WriteLine("The value of obj is : {0}", obj);  
  9.     if(obj is int// Checking if the type of obj is int  
  10.    {  
  11.         System.Console.WriteLine("The obj is of int type.");  
  12.     }  
  13.     x = 200; // Changing the value of x  
  14.     System.Console.WriteLine("After changing the value of x :");  
  15.     System.Console.WriteLine("The value of x is : {0}", x);  
  16.     System.Console.WriteLine("The value of obj is : {0}", obj);  
  17.     if(obj is int// Checking if the type of obj is int  
  18.    {  
  19.         System.Console.WriteLine("The obj is of int type.");  
  20.     }  
  21.   }  
  22. }  
Output
 
Before changing the value of x,
The value of x is: 100
The value of obj is: 100
The obj is of int type.
After changing the value of x,
The value of x is: 200
The value of obj is: 100
The obj is of int type.
 
Explanation
 
Here, x is an integer variable and is assigned a value of 100 at the beginning. Now an object type variable obj is declared and instantiated with x. This leads to boxing wherein the value of x, that is, 100 is copied and a new object instance is created with the value of 100. We print the values of both ‘x’ and ‘obj’. Since the type of obj is int, the statement in the if block gets executed. Next, the value of x is changed to 200. But this does not affect the value stored in obj since it had been instantiated during runtime.
 
The object reference obj is created on the stack, which references a value of type int on the heap. The difference between the variable x and the object reference obj is illustrated in the following diagram,
 
Introduction To Boxing And Unboxing In C#
 
An Important Note
 
Value Data Type variables are always stored in Stack memory whereas references in Reference Data Type variables are always stored in Heap memory.
 

What is Unboxing in C#?

 
Definition
 
It is the process of converting a Reference Data Type to a Value Data Type. This process is an implicit conversion. It consists of first checking whether the object instance is a boxed value of the given Value Type.
 
Syntax 
  1. object objectName;  
  2. dataType varName = (dataType) objectName;  
Here, objectName is the name of the object instance that is to be unboxed. varName is the name of the variable into which the object instance will be unboxed into. The data type of both the variable and the object instance must be the same, otherwise, an exception will be thrown.
 
Example
 
Let us consider the following code: 
  1. using System;  
  2. class Sample {  
  3.   static void Main() {  
  4.     int x = 100;  
  5.     object obj = x; // Boxing  
  6.     int y = (int)obj; // Unboxing  
  7.     System.Console.WriteLine("Before changing the value of obj :");  
  8.     System.Console.WriteLine("The value of x is : {0}", x);  
  9.     System.Console.WriteLine("The value of obj is : {0}", obj);  
  10.     System.Console.WriteLine("The value of y is : {0}", y);  
  11.   
  12.       
  13.     x = 200;  
  14.     obj = x; //Boxing  
  15.     System.Console.WriteLine("After changing the value of obj :");  
  16.     System.Console.WriteLine("The value of x is : {0}", x);  
  17.     System.Console.WriteLine("The value of obj is : {0}", obj);  
  18.     System.Console.WriteLine("The value of y is : {0}", y);  
  19.       
  20.   }  
  21. }  
Output
 
Before changing the value of obj,
 
The value of x is: 100
The value of obj is: 100
The value of y is: 100
 
After changing the value of obj,
 
The value of x is: 200
The value of obj is: 200
The value of y is: 100
 
Explanation
 
Here, x is an integer variable and is assigned the value 100 initially. Then x is boxed into obj using boxing. Now, obj is unboxed into another integer variable y using explicit unboxing. The variable y now contains the value 100. Now the value of x is changed and x is again boxed to obj. However, this does not affect the variable y since it has already been instantiated during its declaration.
 
The variables x and y are created on the stack. The object reference obj is created on the stack, which references a value of type int on the heap. The following diagram illustrates it,
 
Introduction To Boxing And Unboxing In C#
 
The item being unboxed must be a reference to an object that was previously generated by boxing an instance of that value type for unboxing to succeed at run time. A NullReferenceException is thrown while attempting to unbox null. An InvalidCastException is thrown when attempting to unbox a reference to an incompatible value type.
 
Example to demonstrate incorrect unboxing,
 
Let us consider the following code,
  1. using System;  
  2. class Sample {  
  3.   static void Main() {  
  4.   try  
  5.   {  
  6.     int x = 100;  
  7.     object obj = x; // Boxing  
  8.     short y = (short)obj; // Unboxing with mismatched types   
  9.     System.Console.WriteLine("The value of x is : {0}", x);  
  10.     System.Console.WriteLine("The value of obj is : {0}", obj);  
  11.     System.Console.WriteLine("The value of y is : {0}", y);  
  12.   }  
  13.   catch (System.InvalidCastException e)  
  14.     {  
  15.         System.Console.WriteLine("{0} Error: Incorrect unboxing.", e.Message);  
  16.     }  
  17.       
  18.   }  
  19. }  
Output
 
The specified cast is not valid. Error: Incorrect unboxing.
 
Explanation
 
Here, the object reference obj is of type int but the variable y is of type short. So, when we try to unbox obj into the variable y we get an exception thrown which is caught by the catch block and the appropriate message is shown.
 

Conclusion

 
In C#, boxing and unboxing help in the integration of the Value Data Types and the Reference DataTypes. This integration of the type systems gives value types the advantages of object-ness without adding excessive overhead. Int values are simply 32-bit values for programs that don't need int values to behave as objects. This functionality is available on-demand for programs that need int values to behave like objects.