The .NET 2.0 KeyedCollection maybe your most valuable!

September 27, 2007 19:08 by garrymc

When I work with collections I’ll often want to retrieve information from the collection by its key. So my options are usually to make use the following generic collection (who uses any other type of collection now? Unless you’re stuck on .NET 1.1):

   1: System.Collections.Generic.Dictionary<TKey,TValue>

This is great collection except if you want to ever serialize it! Then you’ll have some problems. So the issue becomes do I want a collection which is searchable via an index and is serializable or one that is keyed but can’t be serialized. The problem however, is that in a lot of cases you actually want to be able to use both methods, that is search by ordinal number or index and be able to search by a key, which maybe a business key. To solve this issue many have resorted to inheriting from IList<T> then adding another item overload which iterates through the collection until you find a match. This works, but is probably not too efficient on large collections. Also it’s a pain to have to write this code each time.

With the introduction of .NET 2.0 Microsoft released a collection object which doesn’t get a lot of press. The reason why it’s not discussed very often is because it’s only provided in an abstract form. That is you have to create a concrete implementation before you can use it. As it turns out this is not that hard to do. For example the following C# code is an example of a simple implementation for an Order class:

   1: using System.Collections.ObjectModel;
   2:  
   3: public class Order
   4: {
   5:     private string _orderNumber = "";
   6:  
   7:     public Order(string orderNumber)
   8:     {
   9:         _orderNumber = orderNumber;
  10:     }
  11:  
  12:     public string OrderNumber
  13:     {
  14:         get { return _orderNumber; }
  15:         set { _orderNumber = value; }
  16:     }
  17: }
  18: public class OrderCollection : KeyedCollection<string, Order>
  19: {
  20:     protected override string GetKeyForItem(Order item)
  21:     {
  22:         return item.OrderNumber;
  23:     }
  24: }

So the only thing you need to do is inherit from the KeyedCollection<TKey,TItem> class and implement the abstract method GetKeyForItem. The return of which is the value that makes up the key for the Order object, which in this case is the OrderNumber. You will now be able to access the Orders via both the index and the OrderNumber:

   1: OrderCollection orders = new OrderCollection();
   2: orders.Add(new Order("1008"));
   3:  
   4: Order o = null;
   5: o = orders[0];
   6: o = orders["1008

So we now have a new option to provide both index and keyed functionality that is serializable without having to resort to the old techniques and it’s much faster too!

sidenote: behind the scenes the new collection keeps track of the keys in an dictionary, so the speed is comparable to using a standard dictionary class

However, for some of the projects I work on having a single key isn’t enough, I need to have the ability to search by multiple keys because the business key is a composite. I find that most business type keys are composite unless they are for Orders or Customers which normally have a single business key. I’ll discuss how you can extend the KeyedCollection class to provide this functionality in a future post.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList
kick it on DotNetKicks.com

Currently rated 3.1 by 8 people

  • Currently 3.125/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments