Generics have got to be one of my favorite additions to the 2.0 Framework. The standard generics in the 2.0 Framework are in the System.Collections.Generic namespace. They include classes such as Dictionary, Queue, List, SortedDictionary and Sorted List. But I’m getting a little ahead of myself.

What is a generic?

The short answer to this question is that generics are a way to implement type safe collections in the .NET 2.0 Framework. They also allow software developers to create code that is more reusable, because data structures aren’t tied to specific data types. Examples of data structures that are tailor made for generics are stacks, linked lists and queues. With generics, you can write a type safe implementation of a stack one time, and it can be used for any data type you want.

Why do I like generics?

The main thing I like about generics is that it makes your code type safe. The following example shows why having type safe code is so important. This is a very simple example of the problems that you can run into when your collections are not type safe. This example will compile because the compiler can’t detect errors from boxing and unboxing, but it will throw an InvalidCastException if you try to run it.

int number1, testNumber;
double number2;

// Give our numbers some values for testing.
number1 = 5;
number2 = 3.7;

// Declare a normal array list without using generics.
ArrayList myList = new ArrayList();

// In order to store all of our numbers in the list, we need to “box” them.
// We weren’t paying attention
myList.Add((object)number1);
myList.Add((object)number2);

// Later on in the program we need our numbers back, so we “unbox” them.
// But we accidently put a double and an integer in our ArrayList.
// This is VERY BAD!!!
foreach (object myNumber in myList)
  testNumber = (int)myNumber;


The C# example above illustrated an InvalidCastException, but the equivilent code in VB.NET would be even worse. In VB.NET, the conversion would have been allowed but there would have been logic errors. Any calculations done with the numbers would have been wrong, which is a disaster. I should point out that you can change this behavior in VB.NET, that is with the default settings. The reason for this is that VB.NET allows both widening and narrowing conversions by default, where narrowing conversions require explicit conversion in C#.

Another positive for generics is that you get code that is more efficient and more readable. You do not have to pay the performance penalty associated with boxing and unboxing, and you don’t have to cast objects to their real datatypes to do any operations on them.

Constraints??

Generics can also be “constrained” so that you can take advantage of specific methods of a class or interface. For instance…you are creating a collection and you want to be able to sort the members of your collection. Being able to use the CompareTo() function would be nice. A constraint is a way to force any member of a collection to meet certain criteria. In this case, we could restrict the collection to data types that have implemented the IComparable interface. Here is an example of constraining.

// Our class is a generic class, and we have
// constrained it so that only data types that
// have implemented the IComparable interface can
// be inserted.
public class myClass
    where T : IComparable
{
  // Member variables of our class.
  private T _firstVal;
  private T _secondVal;
 
// Constructor. Pass in 2 of whichever data type is being used.
  public myClass(T first, T second)
  {
    // Set the values of our member variables through the contructor.
    _firstVal = first;
    _secondVal = second;
  }
 
// This function is the reason we constrained our class to
  // only accept data types that have implemented the IComparable
  // interface. We want to guarantee that the CompareTo function
  // is availabe to us.
  public T Max()
  {
    // Use the CompareTo function to determine which of our
    // member variables is bigger.
    if (_secondVal.CompareTo(_firstVal) < 0)
      return _firstVal;
    else
      return _secondVal;
    }
}


Generics are a very powerful construct introduced in the .NET 2.0 Framework. The ability to make collections type safe is a blessing, and the ability to crank out code that is more readable, as well as more reusable, is something that any developer can appreciate. I know I do.