Sunday, October 15, 2006

.NET 2.0 Fun With Generics

So I spent this past weekend playing with Generics. For those of you who haven't used them yet, they are a way to "generalize" your code while still maintaining type safety in .NET 2.0. You can do some very powerful things with them, and some of the native implementations can save you a ton of work.

First of all, there's the List object in the new namespace System.Collections.Generic. This namespace is added by default to all of your class files when you create them in Visual Studio. This allows you to create lists of objects while telling the list the type of object you want to add, whereas in the past with Arrays or Dictionaries you had to check for the type or cast it correctly to make sure the list contained objects of the same type. For example:


List<int> oIntegers = new List<int>();


This will create a new list that will only allow ints to be added to it. In addition, you get type safety when enumerating or using for loops on the List:


foreach(int i in oIntegers)
{
i++;
}


In the past you would have had to cast this to int or check the type to make sure it would not break during the loop, but now because you've told the List what object type to expect, you have type safety. This also works when accessing an object by index:


int iFirst = oIntegers[0];


This will not require casting because the List already knows that any object within its collection will be an int. This is a great improvement over the collection objects in .NET 1.1.

That's not the only thing you can do with Generics. You can also create classes that will contain and interact with various types of objects as well. One of the things that I've always been upset about is the inability to list the members of an Enum. If you've tried this you know what I mean...you want to be able to take an Enum and bind it to a dropdownlist or some other control so users can choose from each of the types and set it on an object. Well now, with a simple Generics based class that derives from List, you can do that:


public class EnumList<t> : List<t>
{
public EnumList()
{
try
{
string[] sNames = Enum.GetNames(typeof(t));
foreach (string sName in sNames)
{
base.Add((t)Enum.Parse(typeof(t), sName));
}
}
catch(Exception e)
{
throw new Exception("Not an enum type", e);
}
}
}


By placing a <t> behind your class definition (or "(Of T)" in VB.NET) you can hand your class a type to interact with, and use that to strongly type items added to your object. In this case, I am going to pass an Enum in as when creating the object, and in the body of the constructor, I will grab the GetNames() method off the Enum class and pass it the type of the object I was handed. Then I can loop through the items in the Enum and add it to the List I've derived from. Once that is done, I now have an object I can use for DataBinding to any bindable control, including DropDownLists on Web Forms.

Here's how you would instantiate it:


public enum enLocomotion
{
Fly,
Walk,
Slither,
Swim
}
public class Animal
{
public List<enLocomotion> Locomotions
{
get
{
return new EnumList<enLocomotion>();
}
}
}




By telling the EnumList you wish it to use the enLocomotion,
the List that the class derives from will populate with
"Fly", "Walk", "Slither", and "Swim" on the fly. This way,
if you add a new item to the Enum, it will automatically
get picked up without any code changes.


Animal oAnimal = new Animal();
this.DropDownList1.DataSource = oAnimal.Locomotions;
this.DropDownList1.DataBind();




Have fun with Generics! I know I will.

Talk to you later,



Rob