Performance Guideline: Use Generics To Eliminate the Cost Of Boxing, Casting and Virtual calls

Here's the next .NET Framework 2.0 performance guideline for review from Prashant Bansode, Bhavin Raichura, Girisha Gadikere and Claudio Caldato.

Use Generics To Eliminate the Cost Of Boxing, Casting and Virtual calls

Applies to

  • .NET 2.0

What to Do

  • Use Generics to eliminate cost of boxing, casting and virtual calls

Why
Generics can be used to improve the performance by avoiding runtime boxing, casting and virtual calls.

List<Object> class gives better performance over ArrayList.  An example benchmark of a quick-sort of an array of one million integers may show the generic method is 3 times faster than the non-generic equivalent. This is because boxing of the values is avoided completely. In another example, the quick-sort of an array of one million string references with the generic method was 20 percent faster due to the absence of a need to perform type checking at run time.   You results will depend on your scenario. Other benefits of using Generics are compile-time type checking, binary code reuse and clarity of the code.

When
Use Generics feature for defining a code (class, structure, interface, method, or delegate) which has to be used by different consumers with different types.

Consider replacing a generic code (class, structure, interface, method, or delegate), which does an implicit casting of any type to System.Object and forces the consuming code to cast between Object references to actual data types.

Only if there is a considerable number (>500) to store consider having a special class, otherwise just use the default List<Object> class.
List<Object> gives better performance over ArrayList as List<Object> has a better internal implementation for enumeration.

How
The following steps show how to use generics for various types.

Define a generic class as follows.
    public class List<T>

Define methods and variables in generic class as follows.
    public class List<T>
   {
      private T[] elements;
      private int count;  
      public void Add(T element)
      {
              if (count == elements.Length)
                 Resize(count * 2);
              elements[count++] = element;
      }  
      public T this[int index]
     {     
           get { return elements[index]; }     
           set { elements[index] = value; }  
      }
    }

Access generic class with required type as follows
    List<int> intList = new List<int>();
    intList.Add(1);
 ........
    int i = intList[0];

Note The .NET Framework 2.0 provides a suite of generic collection classes in the class library. Your applications can further benefit from generics by defining your own generic code

Problem Example
An Order Management Application stores the domain data Item, Price, etc in Cache using ArrayList. ArrayList accepts any type of data and implicitly casts into objects. Numeric data like Order number, customer id, etc are wrapped to object type from primitive types (boxing) while storing in the ArrayList. Consumer code has to explicitly cast the data from Object type to specific data type while retrieving from the ArrayList. Boxing and un-boxing requires lot of operations like memory allocation, memory copy & garbage collection which in turn reduces the performance of the application.

Example code snippet to add items to ArrayList or to get/set items from the ArrayList

    ArrayList intList = new ArrayList();

    //Cache data in to array

    intList.Add(45672);           // Argument is boxed
    intList.Add(45673);           // Argument is boxed

    //Retrieve data from cache
    int orderId = (int)intList.Item[0];  // Explicit un-boxing & casting required

Solution Example
An Order Management Application stores the domain data Item, Price, etc in Cache. Using Generics feature avoids necessity of run time boxing and casting requirements and makes sure of compile time type checking

Implement the defining code for generic class. Generic class can be implemented only if required, else default List<T> class can be used
    //Use  to allow consumer code to specify the required type

    class OrderList{

    //Consumer specific type array to hold the data
   T[] elements;
    int count;

    //No implicit casting while adding to array
    public void Add(T element) {

    //Add data to array as an object
    elements[count++] = element;
    }

    // Method to set or get data
    public T this[int index] {

    //Returns data as T type
      get { return elements[index]; }

    //Set the data as T type
      set { elements[index] = value; }
      }
    }

   Initiate the class with specifying as int data type
    OrderList intList = new OrderList();

    //Cache data in to array
    intList.Add(45672);           // No boxing required
    intList.Add(45673);           // No boxing required

    //Retrieve data from cache
    int orderId = intList[0];  // Un-boxing & casting not required

Additional Resources