Blog Archive

Tuesday, July 18

Ruby Closures

This guide covering closures in Ruby by Paul Cantrell is very insightful. It's written as a Ruby script to be both executed and read. Thanks to Ruby Inside for linking to it.

Tuesday, July 11

JSON Serialization Using C# 3.0 Extension Methods

This post on JSON Serialization Using Extension Methods is a nice demonstration of an elegant solution made possible with extension methods. Nice job, Keith.

Friday, July 7

Collection<T> and explicit interface implementations

Say you're looking at Collection<T> and ReadOnlyCollection<T> in the System.Collections.ObjectModel namespace. You think, “I could use those! In fact, there's a collection I've been meaning to write for awhile:”

class StringCollection : Collection<string>
{
    public StringCollection(params string[] strings) : base(strings) { }

    public string Join(string separator)
    {
        // clearly this is not an efficient solution!
        string[] strings = new string[Items.Count];
        Items.CopyTo(strings, 0);

        return String.Join(separator, strings);
    }
}

class Program
{
    static void Main(string[] args)
    {
        StringCollection strings = new StringCollection("one", "two", "three");
        Console.WriteLine(strings.Join(", "));
    }
}

// Output:
// one, two, three

Perfect! That's exactly what you expected.

Next, you decide to modify your program. You want to add another string:

static void Main(string[] args)
{
    StringCollection strings = new StringCollection("one", "two", "three");
    strings.Add("four");
    Console.WriteLine(strings.Join(", "));
}

Builds fine and… NotSupportedException Collection is read-only!

But wait, we inherited from Collection<T>, not ReadOnlyCollection<T>. What gives?

Well, when we called the base constructor for Collection<T>, we gave it an IList<string>. Okay, so really we gave it an Array of strings, but it was implicitly converted to an IList<string>. That IList was stored as a field within the Collection wrapper (accessible via the protected Items property).

Calling Add calls the explicitly implemented interface member IList.Add on the string[] which (from the docs:) Throws a not supported exception in all cases.

So, how can we modify the StringCollection so that it continues to call the appropriate base constructor, but coerces the string[] to something a bit more useful?

One possibility is to check the IsReadOnly property of the IList before passing it along, like so:

class StringCollection : Collection<string>
{
    public StringCollection() : base() { }
    public StringCollection(params string[] strings) : this((IList<string>) strings) { }
    public StringCollection(IList<string> strings) : base(strings.IsReadOnly ? new List<string>(strings) : strings) { }

    // ...
}

I'm sure there are better ways, though. Any ideas?

Monday, July 3

NDoc

Right about the time I discovered NDoc, we started running pre-release bits of the 2.0 .NET Framework. It was pretty frustrating to discover such a useful tool that didn't work at all with the new features. Even more frustrating has been the lack of updates as I've checked back in on the project.

Well, it turns out Jonas Lagerblad is my 2.0 documentation generation hero. It looks like the updated NDoc still isn't compatible with Visul Studio 2005 solution files, but pointing at an assembly+generated xml works great. Thanks, Jonas!