Wednesday, August 08, 2007

Boxing/Unboxing

Its been nearly three years since I last blogged and what better topic to start blogging back again than boxing/unboxing.
Most of the literature that I can find online tells me what is a boxing/unboxing operation or what are its disadvantages but none could definitively answer to the question that came up during a recent code review. Whether this code causes boxing/unboxing
class Class1
{
int i = 10;
static void Main(string[] args)
{
Class1 x = new Class1();
int a = x.i; //unboxing??
x.i= 20; //boxing??
}
}
I myself when initially came across the concept of boxing/unboxing used to think that the above code will cause box and unbox operations to be called but that's not the case. The above code does not cause boxing/unboxing.
The idea of boxing unboxing is a little little difficult to grasp and I have found lots of people(including myself) struggling with it. There is an article on type fundamentals by Jeffrey Richter which may help explain things and also there is a blog post by David Cumps which gives a nice visual explanation of boxing/unboxing
To figure out in the C# code if it has any box operation look for the following
  1. An instance of a value type is assigned to a variable/field/property of the type object
  2. An instance of a value type is cast to an instance of an object type
  3. An instance of a value type is passed to a method/property indexer which has object type as a parameter.
To figure out in C# code if it has any Unbox operation check whether an instance of a type object is being cast to an instance of a value type.
Below are the few common cases of boxing and unboxing
int j;
int i = 10; // can be any value type like float, double, Point, DateTime, structures etc.
//The standard example
object o = i; //implicit boxing
o = (object)i; //explicit boxing
j = (int)o; //unboxing
//String.Format and its variations
string.Format("Boxing {0}",i); //implicit boxing
Console.WriteLine("Boxing {0}",i);
StringBuilder strBuild = new StringBuilder();
strBuild.AppendFormat("Boxing {0}",i); //implicit boxing
//Collections
ArrayList list = new ArrayList();
list.Add(i); //implicit boxing
list.BinarySearch(i); //implicit boxing
list.IndexOf(i); //implicit boxing
list.Insert(2,i); //implicit boxing (only for i)
list.LastIndexOf(i); //implicit boxing
list.Remove(i); //implicit boxing
j = (int) list[0]; //unboxing
Hashtable coll = new Hashtable();
coll.Add(i,i); //implicit boxing(twice)
coll.Contains(i); //implicit boxing
coll.ContainsKey(i); //implicit boxing
coll.ContainsValue(i); //implicit boxing
coll.Remove(i); //implicit boxing
j = (int) coll[i]; //implicit boxing for indexer and unboxing for assignment
//DataTable
DataTable dt = new DataTable();
dt.Columns.Add("UntypedColumn");
dt.Columns.Add("IntColumn",typeof(int));
DataRow dr = dt.NewRow();
dr["UntypedColumn"] = i; //implicit boxing
dr["IntColumn"] = i; //implicit boxing
j = (int) dr["UntypedColumn"]; //unboxing
j = (int) dr["UntypedColumn"]; //unboxing

2 comments: