|
An Unsorted SortedDictionary
Published: 10/31/2007 |
|
I have to admint this tip is going to seem a little strange. What I am about to show you how to do is create a SortedDictionary that doesn't sort its members. Why would I waste my time doing this, you ask? The answer is simple: I came across a need for this in the "real world" (i.e. work), and expect someone else may as well. So here it is.
First I'll explain why this was needed. As part of the Document Object Model for a new application I am working on, I created a BaseCollection class that all of the collections in the DOM inherit from. In this particular application, the collections should all be sorted, either in ascending order (based on an "Order" property of each item) or in a random order. To achieve this, the BaseCollection passes an IComparer object to the base constructor, either using one designed to sort the items in the list by Order or to randomly sort the items (NOTE: check out this article for information about how to create a custom IComparer, and this article for an example of how to randomly sort lists).
This all worked well and good until I came across some business requirements for a collection that inherited from this base class (and it had to inherit from this base class due to other business requirements) with one major difference: the items in this list must stay in the order in which they were added to the list. In other words, they cannot be sorted. Clearly to adhere to this requirement alone, it would have made much more sense to use a base class that inherited from Dictionary instead of SortedDictionary, but I was tied to my base class (and therefore SortedDictionary) and therefore stuck. After a few moments of hand-wringing and agonizing, I realized that another custom IComparer would solve all of my problems.
The following IComparer implementation, when passed to a SortedDictionary, will convert the SortedDictionary effectively to a regular Dictionary - the items in the list will remain in the order in which they were added to the list:
VB:
Class UnsortedComparer
Implements IComparer
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
If (CType(x, IComparable).CompareTo(y)) = 0 Then
Return 0
Else
Return -1
End If
End Function
End Class
C#:
class UnsortedComparer : IComparer
{
public int Compare(object x, object y)
{
if (((IComparable)x.CompareTo(y) == 0)
return 0;
else
return 1;
}
}
Nice and simple, just the way I like it. Basically what this does is place each item at the end of the list as it is added, since that is when the comparison is done. This results in a list that is sorted according to the order in which the items were added to the list. You have to return "0" if the items are identical, otherwise accessing the list by key won't work properly (as the same algorithm that is used for sorting is used for key access).
Editor's Note: This article was originally posted earlier this year but I pulled it because the code wasn't working properly. It's been reposted now and seems to work in all situations - feel free to send me an e-mail if you have any problems with it...
Questions or Comments? .
VB to C# and C# to VB translation provided by Instant C# and Instant VB.