Understanding Generics—Boxing Issues and Strongly Typed Collections


Jump to: navigation, search
CSharp-Online.NET:Articles
C# Articles

Understanding Generics

© 2006 Andrew Troelsen

Boxing Issues and Strongly Typed Collections

Strongly typed collections are found throughout the .NET base class libraries and are very useful programming constructs. However, these custom containers do little to solve the issue of boxing penalties. Even if you were to create a custom collection named IntCollection that was constructed to operate only on System.Int32 data types, you must allocate some type of object to hold the data (System.Array, System.Collections.ArrayList, etc.):

public class IntCollection : IEnumerable
{
   private ArrayList arInts = new ArrayList();
   public IntCollection() { }
 
   // Unbox for caller.
   public int GetInt(int pos)
   { return (int)arInts[pos]; }
 
   // Boxing operation!
   public void AddInt(int i)
   { arInts.Add(i); }
 
   public void ClearInts()
   { arInts.Clear(); }
 
   public int Count
   { get { return arInts.Count; } }
 
   IEnumerator IEnumerable.GetEnumerator()
   { return arInts.GetEnumerator(); }
}

Regardless of which type you may choose to hold the integers (System.Array, System.Collections.ArrayList, etc.), you cannot escape the boxing dilemma using .NET 1.1. As you might guess, generics come to the rescue again. The following code leverages the System.Collections.Generic.List<> type to create a container of integers that does not incur any boxing or unboxing penalties when inserting or obtaining the value type:

static void Main(string[] args)
{
   // No boxing!
   List<int> myInts = new List<int>();
   myInts.Add(5);
   // No unboxing!
   int i = myInts[0];
}

Just to prove the point, the previous Main() method results in the following CIL code (note the lack of any box or unbox opcodes):

.method private hidebysig static void Main(string[] args) cil managed
{
   .entrypoint
   .maxstack 2
   .locals init ([0] class [mscorlib]System.Collections.Generic.'List`1'<int32>
      myInts, [1] int32 i)
   newobj instance void class
      [mscorlib]System.Collections.Generic.'List`1'<int32>::.ctor()
   stloc.0
   ldloc.0
   ldc.i4.5
   callvirt instance void class [mscorlib]
      System.Collections.Generic.'List`1'<int32>::Add(!0)
   nop
   ldloc.0
   ldc.i4.0
   callvirt instance !0 class [mscorlib]
      System.Collections.Generic.'List`1'<int32>::get_Item(int32)
   stloc.1
   ret
}

So now that you have a better feel for the role generics can play under .NET 2.0, you’re ready to dig into the details. To begin, allow me to formally introduce the System.Collections.Generic namespace.


Previous_Page_.gif Next_Page_.gif




Personal tools

AbeBooks.com &#8211; Textbooks