Thursday, January 5, 2012

What is Boxing and Unboxing in c#?

Boxing and Unboxing

You can convert value types to reference types and back again. When a value type variable needs to be converted to a reference (object) type, an object (a box) is allocated on the managed heap to hold the value and its value is copied into the box. This process is known as boxing. Boxing can be implicit or explicit, as shown in the following code.

int p = 123;
Object box;
box = p; // Implicit boxing
box = (Object)p; // Explicit boxing with a cast

Boxing occurs most often when you pass a value type to a method that takes an Object as its parameter. When a value in an object is converted back into a value type, the value is copied out of the box and into the appropriate storage location. This process is known as unboxing.

p = (int)box; // Unboxing

Boxing issues are exacerbated in loops or when dealing with large amount of data such as large-sized collections storing value types.

To help ensure that boxing and unboxing does not significantly impact your code's performance, consider the following recommendations:

● Avoid frequent boxing and unboxing overhead.

● Measure boxing overhead.

● Use DirectCast in your Visual Basic .NET code.

Avoid Frequent Boxing and Unboxing Overhead

Boxing causes a heap allocation and a memory copy operation. To avoid boxing, do not treat value types as reference types. Avoid passing value types in method parameters that expect a reference type. Where boxing is unavoidable, to reduce the boxing overhead, box your variable once and keep an object reference to the boxed copy as long as needed, and then unbox it when you need a value type again.

int p = 123;
object box;
box = (object)p; // Explicit boxing with a cast
//use the box variable instead of p

Collections and Boxing

Collections store only data with base type as Object. Passing value types such as integers and floating point numbers to collections causes boxing. A common scenario is populating collections with data containing int or float types returned from a database. The overhead can be excessive in the case of collections due to iteration. The problem is illustrated by the following code.

ArrayList al = new ArrayList();
for (int i=0; i<1000;i++)
al.Add(i); //Implicitly boxed because Add() takes an object
int f = (int)al[0]; // The element is unboxed

To prevent this, consider using an array instead, or creating a custom collection class for your specific value type. You must perform unboxing with an explicit cast operator.

This will make it possible to write variations of the above code with no boxing.

Measure Boxing Overhead
There are several ways to measure the impact of boxing operations. You can use Performance Monitor to measure the performance impact of boxing overhead on the resource utilization and response times for your application. To do a static analysis of where exactly you are affected by boxing and unboxing in your code, you can analyze MSIL code. Search for box and unboxinstructions in MSIL by using the following command line.

Ildasm.exe Yourapplication.dll /text | findstr box
Ildasm.exe Yourapplication.dll /text | findstr unbox

exactly you optimize the boxing overhead. The overhead is significant in places where there are frequent iterations such as loops, inserting, and retrieving value types in collections. Instances where boxing occurs only once or twice are not worth optimizing.