Welcome to EMC Consulting Blogs Sign in | Join | Help

Anthony Steele's Blog

Generic lists

I have spent a fair amount of time in the past writing business objects, and as soon as we'd made a "Widget" class we needed a "WidgetList" class. I got pretty practiced at throwing these lists out quickly since they were all the same. Depending on the particular project's design decision, we'd encapsulate or inherit from a weakly-typed list.

A large number of innovations in computer programming are finding new ways to adhere to the ideal of DRY: Don't Repeat Yourself. So now with generics, all you need is "List<Widget> myList = new List<Widget>();"

The problem is that these lists weren't actually all the same. They did all had Add() and Clear() methods, Count and Items[] properties, and so on.  But the item class was created because it wasn't just like anything else existing, and this carried over to the list. For instance, if it was a list of integers you wanted the Sum, Min, Max and Mean of the contents. If it was an address list, there'd be a method to find the primary billing address in a list of addresses for a client, and so on. Good object-oriented style says that those methods should be attached to the object where they do their work, i.e. on the list.

There are ways to do this in generics. Here’s a generic subclass of a generic list:

public class MyList<T> : List<T>

{

}

And a specific subclass of a generic list:

public class IntList : List<int>

{

    // sum all the ints in the list

    int Sum()

    {

        int result = 0;

        foreach (int item in this)

            result += item;

        return result;

    }

}

The only drawbacks to this technique that I know of are that the attributes that are attached to List<T> are not automatically attached to its subclasses. List<T> is marked [Serializable], but MyList<T> isn’t, unless you do so manually. It’s easy to forget that it’s not a complete drop-in-replacement unless you add the same attributes as the base class.  John Rayner has noted similar issues.

Here’s a more complex example, using both generic and specific subclasses:

public class BusinessObject

{

.. virtual methods for all business objects

}

public class BusinessObjectList<T>: List<T>

    where T: BusinessObject

{

… methods on lists of business objects

}

public class Widget: BusinessObject

{

}

public class WidgetList: BusinessObjectList<Widget>

{
  .. a list of widgets, with businessObject-specific and widget-specific methods

}

And finally an odd one, a class that participates in its own base class:

    public class GenericBase<T>

    {

      .. protected methods on T

    }

    public class Widget2 : GenericBase<Widget2>

    {

    }

Which means that Widget2 has access to all the inherited generic methods, in form strongly typed for its own use. I have not yet worked out if using this technique is a good idea or not. I got this example from a book that I was looking through; but the title escapes me now.

Published 15 November 2006 12:49 by Anthony.Steele

Comments

 

Anthony Steele's Blog said:

A while back (has it been two years already?) I wrote about using the new generics feature in C# to make

November 28, 2008 20:55
Anonymous comments are disabled

About Anthony.Steele

Programmer in c# for Conchango

This Blog

Syndication

Powered by Community Server (Personal Edition), by Telligent Systems