Using Lists and Collections in .NET

Hashtable Sample Code

One of the common uses for Hashtables is enabling a specified identifier to quickly retrieve items. Examples could be phone numbers, Social Security numbers, database identity columns, and so on. The following sample code demonstrates the use of a Hashtable. It simply uses a random number generator to create identities, checks to see whether they exist, and, if not, adds them to the Hashtable:

The random number generator likely won't produce any clashes with such a short loop, but it demonstrates the concept. The sample code assumes reuse of the TestItem class and as with the previous example, the code is limited to what is not generated by default in a console application.

CollectionBase

A CollectionBase is similar to ArrayLists and Hashtables in that it is a list. However, a CollectionBase is an abstract class that allows you to define type-specific lists. For example, if you wanted a list of just TestItem from the previous sample code, you would use the CollectionBase as the base class for your object and then create the appropriate methods or override the desired functionality.

Generics

If you recall, the ArrayList, Hashtable, and other list types support use of any type of object. This is great in terms of flexibility, but can easily lead to logic mistakes and performance issues related to the overhead associated with boxing and unboxing types. Because any type can be used, there is no type checking at compile time to enforce consistent storage of the same type within the list. Thus, along with your simple TestItem class, you could also mistakenly add a DataSet or some other type of object to the same ArrayList or Hashtable and it would not cause a compile error. In most scenarios, the same type of object is used within a list and not different types. Meaning, rarely would you want to put a TestItem and a DataSet into the same list. This can lead to logic errors that take time to track down and debug.

In the 1.0 and 1.1 versions of the Microsoft .NET Framework, the workaround for the above problems was to create your own wrappers around ArrayList, Hashtable, and the like, and limit the specific types that can be assigned. Another solution would be to create your own type-specific class with CollectionBase as the base class. For example, you'd have to create your own TestItemArrayList that behaves like an ArrayList but allows only the methods to accept TestItem types. This is not ideal because you would have to create a class for each specific type you need, which could lead to a lot of tedious code. Even if you use a code generator to do it for you, this still generates a lot of code that you ultimately need to maintain.

To help solve these problems, the Microsoft .NET Framework version 2.0 will include generics. Many developers with C++ experience recognize generics as what is known in C++ as templates. A generic is a type-safe class that is declared without a specific type applied to it in the definition. Rather, the type is specified at the time the object is used. In the code examples in this article, that would be equivalent to specifying TestItem as the type at the time you declare your ArrayList or Hashtable variables. The effect is that it limits that particular item from holding any type other than a TestItem. The code will not compile if you attempt to assign something such as a DataSet. This helps to easily avoid those costly logic errors and supports a high degree of code reuse.

Generics have other performance advantages as well, but I'll save those for another day. Find an introduction to generics with sample code on MSDN.

Possible Enhancements

In the past, creating type-safe wrappers for objects was handy. With the impending inclusion of generics, I recommend evaluating your timeline against the release of version 2.0 of the .NET Framework to determine whether you need them now or whether you can just wait. For those who already have their own type-safe wrappers, you probably should start planning to replace them with generics for the performance and maintenance benefits.

Future Columns

I've yet to determine the topic of the next column. If you have something in particular that you would like to see explained, e-mail me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C#. You can reach Mark at mstrawmyer@crowechizek.com.