Wednesday, February 18, 2009

Dictionaries

This isn't really related to XNA, I know but oh well.

I'm a big fan of the generic collections. I use them alot - mainly List(Of T) and Dictionary(Of TKey, TValue). Sometimes I have trouble deciding which to use. Is it going to be easier to access by index or by key. Othertimes I need to use a List (have to supply an IList to a particular interface etc.) but would still like the ease of access of the Dictionary.

As well as XNA, I have also been learning WPF. The DataBinding in WPF relies heavily on INotifyPropertyChanged and INotiftyCollectionChanged. Classes implementing the second interface, INotifyCollectionChanged need to be accessable via index. WPF doesn't come with an ObservableDictionary, probably for this reason.

I was browsing MSDN when I came across the OrderedDictionary. After reading its description "Represents a collection of key/value pairs that are accessible by the key or index.", I thought for a moment that I might have found a solution.

A few problems with this one tho.. First, it may be accessable via index - but it's not a list! i.e. it doesn't implement IList or IList(Of T). Second, it isn't Generic. To make it type safe I would have to inherit it each time I wanted to use it etc.

I decided to write my own DictionaryList. It would be Generic and implement:
  • IDictionary(Of TKey, TValue)
  • IList(Of KeyValuePair(Of TKey, TValue))
  • ICollection(Of KeyValuePair(Of TKey, TValue))
  • IEnumerable(Of KeyValuePair(Of TKey, TValue))
  • IDictionary
  • ICollection
  • IEnumerable
Later I decided to mark it as Serializable and implement IDeserializationCallback.

Internally, my new collection stores items in a Dictionary(Of TKey, TValue) as well as a List(Of KeyValuePair(Of TKey, TValue)). It was fairly easy to create, just make sure both of the internal collections stay in sync.

I haven't tested it thoroughly yet but so far it seems to work well. I can see problems if anyone tried to use it with a Key of type Integer. It wouldn't know which of the (overloaded) Default Properties to call:
  • Default Public Property Item(ByVal index As Integer) As KeyValuePair(Of TKey, TValue)
  • or
  • Default Public Property Item(ByVal key As TKey) As TValue

My second class that I created was ObservableDictionaryList. I inherited my newly created class DictionaryList and implemented INotifyCollectionChanged and INotifyPropertyChanged. This class was straight forward and a lot smaller than the first one!

No comments: