Understanding Generics—Boxing Issues and Strongly Typed Collections
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
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.
|

