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.
Blog Archive
Labels
Tuesday, July 18
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!