ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


What Are Generics

by Jesse Liberty, author of Programming Visual Basic 2005
11/28/2005

Generics
Generics provide the ability to create type-safe collections in .NET. The best way to understand Generics is to understand the problem they were designed to solve.

In This Article:

  1. Why Type Safety Is Important
  2. Solving the Problem with Generics
  3. Type-Safe Collections

In .NET 1.x, the built-in collections (e.g., ArrayList, Queue, Stack, Dictionary) were not type-safe. Each of these collections took an Object, and since everything in .NET derives from Object, this meant that each collection would take any instance of any type. Thus, you could comfortably write code that looked like this: [1]

      Dim myArrayList As New ArrayList()
      For i As Integer = 0 To 20
         myArrayList.Add(i)
      Next

The snippet above creates an ArrayList and adds 21 Integers to it. Unfortunately, there is nothing in the ArrayList to prevent you from writing:

      Dim myString As String = "Uh oh, I'm not an Integer"
      myArrayList.Add(myString)

You now have an ArrayList with Integers and a String in it. The technical term for this is "bad." The ArrayList is not type-safe.

Why Type Safety Is Important

Type safety enlists the compiler in finding your bugs. I used to work for a guy named Pat Johnson who said "Save time debugging, don't put any bugs in." Despite that bit of wisdom, most sizable applications have some bugs at first, and, given the choice, you want compile-time bugs rather than run-time bugs. This is because compile time bugs will be found 100 percent of the time you compile your code, while run-time bugs can and will hide in the crevices and interstices of your program; waiting, biding their time, living silently on morsels of syntax until you ship your program, when they will spring out, cackling madly in front of your customers.

There are two other programs with ArrayList-holding objects. First, any time you take an object out, you need to cast it to its "real" type (the collection only knows it is an Object, not that it is an Integer); and second, because you cannot know for sure what is actually in the ArrayList, you find yourself writing code that checks the type of the object before casting it.:

sum = 0
For Each tmpObject As Object In myArrayList
   If TypeOf tmpObject Is Integer Then
      sum += CInt(tmpObject)   'cast to Integer
   End If
Next
Console.WriteLine(sum.ToString())

This code adds all the Integer values in myArrayList, but since it is possible that there are other types in that list (strings, Dogs, Monsters), it must first check the type of each entry to make sure it is an Integer. This makes for ugly code that is error prone and hard to maintain.

C# 1.x and VB.NET programmers cried out for help, "We want a grownup programming language that has type-safe collections." C# 2.0 and Visual Basic 2005 provide the solution with Generics.

Visual C# 2005: A Developer's Notebook

Related Reading

Visual C# 2005: A Developer's Notebook
By Jesse Liberty

Solving the Problem with Generics

The solution to the "I'm Just A Girl Who Can't Say No" [2] attitude of the ArrayList is to use the Generic List (of T) class. The List class has been designed to hold only one type (T); you will define what type that is (Integer, String, etc.) when you make an instance of the class. Thus, you might write something like this:

      Dim myGenericIntegerList As New List(Of Integer)
      For i As Integer = 0 To 20
         myGenericIntegerList.Add(i * 2)
      Next

If you then attempt to add a String, you will receive a compiler error: "Hey! Bozo! You can only add Integers to this collection." (Your compiler wording may vary slightly.)

Since the collection now is known to hold Integers, you neither have to test nor to cast, you can assume (safely) that every member of the collection is an Integer:

sum = 0  ' already declared
For Each tempInt As Integer In myGenericIntegerList
   sum += tempInt
Next

Type-Safe Collections

The .NET Framework provides four type-safe collections that you will use frequently: Lists, Queues, Stacks, and Dictionaries. Here are quick examples of all four to see how easy they are to work with.

Queues

A queue is a First In First Out (FIFO) data structure. Think of a line of people at a ticket window, the first person on line is served first. The most (in)famous use of a Queue in programming is the ubiquitous (and infernal) message: "Your call is important to us, and will be answered in the order received." You can create a type-safe queue like this:

      Dim intQueue As New Queue(Of Integer)
      Dim strQueue As New Queue(Of String)

You are now free to add Integers to the intQueue and strings to strQueue, but not vice versa. There is no need to cast the objects you extract, as you already know their type.

      Dim tempInt As Integer = intQueue.Dequeue()
      Dim tempString as String = strQueue.Dequeue()

Stacks

Stacks are almost identical to queues except that they are Last In, First Out (LIFO) data structure. Think of a stack of dishes at the buffet table (on springs). As you add a dish, you push it onto the stack, and when you want a dish. you pop the top one off.

    Dim intStack As New Stack(Of Integer)
    Dim strstack As New Stack(Of String)

You are now free to add Integers to the intQueue and strings to strQueue, but not vice versa. There is no need to cast the objects you extract, as you already know their type.

     Dim myIntegerVariable As Integer = intStack.Pop()
     Dim myStringVariable As String = strstack.Pop()

Dictionaries

Dictionaries are slightly more complex data structures. They allow you to associate a (relatively small) key with a (relatively large or complex) value. In a traditional dictionary, the key is the word, and the value is the definition, pronunciation, and part of speech.

In .NET you define a dictionary by telling the compiler the type of the key and the type of the value, and these two types do not have to be the same (e.g., you might use an Integer such as an EmployeeID, to be the key and you might make the entire Employee object be the value.

Dim dict As Dictionary(Of String, String) = New Dictionary(Of String, String)

In the case shown, to keep things simple, the key is the two letter String for a postal code, and the value is the name of the state and the capital of that state.

         dict.Add("AL", "Alabama: Montgomery")
         dict.Add("AK", "Alaska: Juneau")
         dict.Add("MA", "Massachusetts: Boston")
         dict.Add("NY", "New York: Albany")

You are now free to access the value by providing the key:

    Dim stateAndCapital as String = dict("MA")

Because the compiler knows the type of the key and the type of the value, you cannot add keys or values of other types without generating a compile-time error, and that makes your dictionary (and queue and stack) type-safe, which, as explained above, is a good thing.


Footnotes

Footnote 1: The code in this article is in Visual Basic 2005 for a number of reasons. First, Generics are most heavily associated with C# (because C++ has templates that are an implementation of Generics) and it is important to realize that the .NET implementation of Generics is cross-language. Second, I was becoming something of a C# snob (sorry, started out in C, then C++, then C#). Third, and most important, at this point every serious .NET developer should be able to at least read both C# and VB 2005; they are the same language with different syntactic sugar. Finally, I just released a new book, Programming Visual Basic 2005, and this gives me a shameless opportunity to flog it relentlessly.

Footnote 2: Oklahoma, Rogers and Hammerstein

Jesse Liberty is a senior program manager for Microsoft Silverlight where he is responsible for the creation of tutorials, videos and other content to facilitate the learning and use of Silverlight. Jesse is well known in the industry in part because of his many bestselling books, including O'Reilly Media's Programming .NET 3.5, Programming C# 3.0, Learning ASP.NET with AJAX and the soon to be published Programming Silverlight.


Return to ONDotnet.com.

Copyright © 2009 O'Reilly Media, Inc.