Register | Login 
View Article  

Current Articles | Categories | Search | Syndication

Generics: An Introduction

By Chad Bryant on Saturday, December 09, 2006 :: 1472 Views :: 0 Comments :: C#, General .NET Programming

Arguably one of the best new aspects of C# 2.0 is Generics.  Generics gives us the best of two worlds.  The one world is the ability to write generic non-type specific code that can be reused with many different types.   The other world is the world of strongly typed objects.  We all know the downsides of working with the object type in .NET.   We have to cast our variable to the real type at run-time which can lead to run-time errors and bypasses the benefits of strongly type codes.  In addition, casting can create performance issues as well.  Another downside to this approach would be the potential boxing and unboxing we would have to do if we were storing, for example, a string or integer (or other value type) in a collection that accepted a reference type object. 

The solution to this issue has been that many developers create different collection classes, for example, for each type of collection so that they have a strongly typed collection to work with.  This avoids the casting and run-time error issues, but creates another problem: Redundant code.  Anyone who knows me and has worked with me knows how much I attempt to avoid writing redundant code.  It makes maintenance much more difficult and error prone, but prior to Generics in .NET 2.0, many felt it was better to do this than to create more generic code that would end up requiring casting, etc.

The solution to these problems is Generics.  I have heard Generics described as strong typed variants and this seems to be an accurate description.  Generics can seem daunting to many who may not be familiar with the concept.  C++ has something similar with C++ Templates, but for many (including myself) .NET 2.0 is their first introduction to this new powerful concept.

It would be prudent to begin with a simple example demonstrating how we might have done things in the old way.  Consider the example below where we want to keep a list of SalesPerson objects.  We might use an ArrayList for this.  ArrayList is a list of objects as in System.Object.  This is pretty generic.  We can store anything in our ArrayList.  Consider the following code:

chad9.gif

The problem with this approach is that we may assume that our code has added only SalesPerson objects to our ArrayList, but what happens if we have a bug and a Part object gets stored in our SalesPerson array list?  The compiler won’t catch this as this is perfectly valid from a compiler perspective.  SalesPerson and Part are both objects as all types in .NET descend from System.Object.  The problem will come when we attempt to retrieve our SalesPerson object out of the array list.  At run-time, we will have to cast the item from the array list to a SalesPerson and if the object stored in the array list is a Part, then this will cause a run-time error.

Having a generic array list is great.  The above approach did solve the problem of not needing a different array list for every type and of course the .NET framework could not accomplish this since Microsoft does not know in advance what objects we are going to create. 

As you’re well aware by now, the answer to our dilemma is Generics!  Let us look again at the code snippet presented above, but this time we will re-write the code using Generics.  The .NET 2.0 framework provides us a generic list class: List<T> where T is a type parameter that represents any class that we might want a list of.  Consider this code:

chad8.gif

Let’s walk through this code and see how this solves our problem.  First, notice the variable declaration for genericSalesPersonList.  It is of type List<SalesPerson>.  Here we are passing into our type List the type SalesPerson as the type to use for this list.  So our list will not be a list of objects, or a list of Parts, or anything else.  It will only be and can only be a list of SalesPerson objects.  If we tried to add to this list anything other than a SalesPerson, then we would get a compile time error.  Perfect!  We have a generic List class that can be reused to store lists of any type but in a strongly typed non-generic way.  Are you beginning to see the power of Generics?   Also notice the third line of code above.  It declares a variable called salesPersonGeneric which is of type SalesPerson.  We want to retrieve an item from our list, but notice we do not have to cast this item to a SalesPerson.  It is already stored as a SalesPerson in the list!  This code will be more efficient and type-safe than the previous code we wrote.

I would like to give another example of where Generics helped our team refactor a class that was several hundred lines of code.  We had a custom IComparer class that we used for sorting of our collections.  Our user interface in a web application used custom objects and custom collections rather than DataSets, etc.  So, using our example above we might have had a SalesPerson class and a SalesPersonCollection class.  If our user interface provided a sales person maintenance form, it would work with SalesPerson and SalesPersonCollection objects.  Our collections provided sorting, filtering, and other features that would be commonly used in such an application and we needed a custom class that implemented the IComparer interface to handle sorting.  We decided we only wanted one IComparer class instead of a comparer class for each type.  So we did not create a SalesPersonComparer then a PartComparer, etc.  We had just one.  However, inside this class we had to write a method to handle the sorting for EVERY type of class that might have a corresponding collection that needed to be sorted.  Each method to handle the sort was basically the same code duplicated over and over again where the only difference was the object being used.  Clearly Generics is a much better way to approach this problem and you should have seen the amount of code that was deleted when we rewrote our Comparer class!!

I hope this short article has helped you see why Generics are so powerful and how they can help you write type safe code that is generic and reusable.  This article did not go into all the .NET generic types provided and was not meant to be an in depth how to article.  My goal was to briefly expose you to what Generics are and what problems they are meant to solve.  I hope you will now explore the wealth of material online and in various books that go into a more detailed and systematic layout meant to teach you all about Generics!  Have fun!



Chad Bryant is a senior developer with The Delta Group, a Greenville, SC based firm providing web based software to the healthcare industry. In addition to programming, Chad enjoys running marathons, spending time with his wife and three daughters, and reading books. Chad can be contacted via email at chadbryant5@charter.net

Previous Page | Next Page

COMMENTS

Currently, there are no comments. Be the first to post one!
Click here to post a comment

Copyright (c) 2009 GSP Developers
Walling Info Systems | Terms Of Use | Privacy Statement