The Missing .NET #2: Collection<T> AddRange()

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a new series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer. It could be a useful class, a technique, a good practice or documentation that should be in the framework but isn’t.


One of the sad, unfortunate truths about Windows Forms development is that you don’t get to use it. That’s right: LINQ, WCF, WPF, maybe even generics, iterators, and the awesomest Winforms control ever, ToolStrip. All of it may be off limits to you, dear WinForms developer, because real people don’t know what the .NET framework is, and don’t care that your app depends on it; nor are they willing to sit through a 24 MB download, apparently. That last one seems really weird to me, a broadband user for 8 years, but, the numbers don’t lie: your users don’t have the framework on their computers. Now, there is hope with Vista — if Microsoft could just advertise it better so everyone’s perception of it isn’t that it sucks balls; it has .NET 3.0 installed by default, but .NET 3.5? Still a separate download.

That never-ending march forward of the .NET framework was a little disheartening to me: I felt the pressure to constantly stay on top of new stuff (and, oh, man is there ever a lot of new stuff since .NET 2.0: WPF, WCF, Workflow, LINQ, C# 3.0, not to mention all libraries the fast-moving ASP.NET team is pumping out), but there was a huge disconnect when I’d have to toil daily in the doldrums of .NET 1.1. So I unplugged, stopped blogging, just gave up on keeping up. “What was the point?” I’d ask.

I don’t really know what has spurred me on lately, but now I’m starting to get that passion back. So, I’ve been looking into some of the new stuff. Rather than jump right in with LINQ, I figured I’d start with some of the language improvements in C# 3.0, and in this post I’m going to go through an example of one of the easiest to grok, and one of the more powerful ones: extension methods.

One of the greatest classes in .NET 2.0 is List<T>. It is seriously awesome and, I assume, quite popular. What makes it so useful isn’t its strongly-typed nature, but the methods it exposes to access the strongly-typed collection, like Find(Predicate<T> match) and Foreach(Action<T> action). We’ve all written methods like this for arrays and ArrayList:

MyType Find(List<MyType> list)
{
    foreach (MyType t in list)
    {
        if (t.MyInt == 42)
            return t;
    }
    return null;
}

to find an element in the list. Or, something like this to perform an operation on every element in the list:

void Find(List<MyType> list)
{
    foreach (MyType t in list)
    {
        DoSomething(t);
    }
}

They’re both standard .NET 1.1 idioms. They clutter your code, it’s boilerplate, but you didn’t really have a choice. With List<T>, you can do these operations more succinctly:

MyType myType = list.Find(delegate(MyType t) { return t.MyInt == 42; });

and

list.ForEach(delegate(MyType t) { DoSomething(t); };

Beautiful!

So, why don’t we see List<T> being used everywhere? Well, the framework design guidelines say you shouldn’t publicly expose List<T>, that you should use Collection<T> instead. Krzysztof Cwalina, co-author of the excellent .NET Framework Design Guidelines, says why here. He has a point: you don’t want to expose methods unnecessarily, but those two above (Find(Predicate) and ForEach(Action) and let’s not forget AddRange()) are so useful. And it’s not unreasonable to want to find an element in a Collection<T> or do something to each element in the collection.

To do this is in the old-fashioned .NET 2.0 days, every time you wanted these methods, you’d have to create a custom collection and implement the method: Yuck. We’re also assuming that you control the collection class; perhaps you’re using a third-party component that exposes a Collection<T>, in which case, you’ll probably have to revert back to the .NET 1.1 idiom.

Now, in the latest and greatest .NET 3.5, you can write those methods once and use them wherever Collection<T> is exposed with extension methods! These things are a great way to add functionality that got missed to classes you don’t own. Consider this convoluted way of printing “Hello world”:

static void Main(string[] args)
{
    MyType[] array = {
                       new MyType{MyString="Hello", MyInt=42},
                       new MyType{MyString="World", MyInt=84},
                       new MyType{MyString="Jason", MyInt=92}
                     };

    List<MyType> list = new List<MyType>();
    list.AddRange(array);

    MyType myType = list.Find(delegate(MyType t) { return t.MyInt == 42; });

    Console.Write(myType.MyString);

    Console.Write(", ");

    Collection<MyType> collection = new Collection<MyType>();
    collection.AddRange(array);

    myType = collection.Find(delegate(MyType t) { return t.MyInt == 84; });
    Console.WriteLine(myType.MyString);
    Console.ReadLine();
}

class MyType
{
    public string MyString { get; set; }
    public int MyInt { get; set; }
}

Note the collection class to print the world half. It’s got the AddRange() and the Find() method that List<T> does, which isn’t in its API. Those are extension methods.

The code that enables that is thus:

public static void AddRange<T>(this Collection<T> collection, IEnumerable<T> values)
{
    foreach (var item in values)
    {
        collection.Add(item);
    }
}

public static T Find<T>(this Collection<T> collection, Predicate<T> predicate)
{
    foreach (var item in collection)
    {
        if (predicate(item))
            return item;
    }
    return default(T);
}

The magic happens with the ‘this’ keyword in the method signature. Extension methods are truly cool: very powerful, and with great power, comes great responsibility. You should use it wisely.

Download the extension methods for Collection<T> here.

4 Replies to “The Missing .NET #2: Collection<T> AddRange()”

  1. Hi! Thank you for your article. In The Visual Studio Code Analysis Team Blog they explained (http://blogs.msdn.com/fxcop/archive/2006/04/27/585476.aspx) how to ensure that we could re-use List methods in our concrete implementation of a generic Collection class, whenever it is necessary. The catch there was that a developer has to remember to call base class constructor : base(new List[Address]()) to guarantee that Collection is actually a List too.
    To make developer’s life easier, I proposed to make a generic Collection class with that special type of constructor and all the “missing” methods as well.
    Please take a look at http://pro-thoughts.blogspot.com/2008/07/generic-listcollection-class-take-2.html and tell me what you think.

  2. I modified the code for the simple FindIndex and Find cases to use a foreach since some collection implementations may have to actually iterate through N elements to get to the Nth element. When possible I try to avoid indexes in a loop due to the potential performance issues.

    With the Find methods, I stored the item being predicated and returned that item rather than getting it again by index due to the reason just mentioned.

  3. Hmmm … why is it

    foreach (var item in collection)

    and not

    foreach (T item in collection)

    …? Is there a difference to it I can’t spot?

  4. In this case, not really. The var keyword just tells the compiler, “figure out this type for me, we both know what it is, so I don’t have to write out the type name.” You can use it anywhere you declare a method variable.

    I can’t say for certain, but I’m pretty sure that the compiler will convert ‘var’ to ‘T’ for us.

Comments are closed.