Generics Rule
Everyday I thank my lucky stars for generics in .NET 2.0. I believe it is the single greatest feature ever to be included in the .NET Framework and its languages, and I cannot imagine having to work without them. It's always fun for me to see the lightbulb go off when developers first grok generics and the power they provide. For most developers it takes a bit of time to get used to generics; I was the same way. But boy oh boy, when you finally do "get" them, it's like a whole new world you want to explore, just to see what you can do.

So allow me to show off generics with a real-world demonstration. The two methods below retrieve a single entity from a data store using NHibernate (the Repository class is a wrapper on the NHibernate API). Don't focus on the NHibernate part. It's here because this was a ready-made example I could use from a real project. Just know that these two methods basically do the exact same thing.

A. The Method Without Generics
public static EntityBase Get(Type entityType, object id)
{
    EntityBase entity = null;

    if (entityType != null)
    {
        if (!entityType.IsSubclassOf(typeof(EntityBase)))
        {
            throw new ArgumentException("Must derive from EntityBase.", "entityType");
        }

        using (Repository rep = new Repository())
        {
            entity = (EntityBase)rep.Session.Get(entityType, id);
        }
    }
    return entity;
}

B. The Method With Generics
public static T Get<T>(object id) where T : EntityBase
{
    using (Repository rep = new Repository())
    {
        return (T)rep.Session.Get(typeof(T), id);
    }
}

Aside from the obvious syntax differences, the first thing you should notice is that the method with generics uses *less* code to accomplish the same task as the method without generics. The most minimal code you have that does what you need is as good as it gets. And I'll spare you what the IL looks like for each method, but know that the IL for the generics method also has less code than it's non-generics counterpart.

To further understand generics, let's look at the interpretation of each method:

Interpretation of Method Without Generics
The method Get takes in a type and an ID and returns an object of type EntityBase. The type is checked for null and is then checked to see if it inherits from (is a subclass of) the EntityBase class. If it's not, an exception is thrown; otherwise, the object is retrieved from the data store using NHibernate and is cast to EntityBase, where it is then returned to the caller.

Interpretation of Method With Generics
The method Get takes in an ID and returns an object of type T where T must inherit from EntityBase. The object is retrieved from the data store using NHibernate and is cast to type T, where it is then returned to the caller.

Heck, even the interpretation of the method with generics is simpler than the non-generics version!

Now take a closer look at the generics method and notice the "where" keyword and its syntax. This basically tells the method that it can't use any type other than ones that derive from EntityBase. So in this case, the use of generics allows for even greater type safety, at least with regards to the entities I'm concerned with. The generics method could've just as easily been written without the "where" keyword and its syntax and it would have worked exactly the same. But in this case I can limit the method to only act on classes of certain types, thus eliminating the call to IsSubclassOf and its possible exception.

This is cool and all, but what do the two methods look like when invoked by a caller? Glad you asked:

Without Generics: Customer customer = Get(typeof(Customer), id);
With Generics: Customer customer = Get<Customer>(id);

There isn't much difference between the two, except that the generics version allows you to simply specify Customer as the generic type instead of using typeof(Customer) as the parameter.

I was showing this stuff today to the development manager at my new client (who can still sling code - gasp!) and I could see the light go on. He said he'd have to get used to the T syntax, but he was excited about it and couldn't wait to start using them on the new project. Hopefully you feel the same way.

Post your comment

Comment