Posts
56
Comments
307
Trackbacks
0
Using KeyedCollection<TKey, TItem>

A little over 2 years ago, I saw my peer’s code that uses the KeyedCollection<TKey, TItem> class.  I never seen it before, and it is actually a pretty nice class.  It is essentially a dictionary class, but with the stipulation that the key for each item added to the dictionary can be retrieved from the item itself. 

With a Dictionary, every time we wanted to add a new item into it, we have to call its Add method, which accepts 2 parameters, the key for the item and the item itself.  In most cases, the key already is in the item, so we’re just reduplicating it.  This KeyedCollection class provides a shortcut since we can just provide it a method so it can get the key for each item added automatically.

The following code show how Dictionary and KeyedCollection can be used:

// Class to contain data stuff
public class MyData
{
   public int Id { get; set; }
   public string Data { get; set; }
 }

// KeyedCollection is an abstract class, so have to derive
public class MyDataKeyedCollection : KeyedCollection<int, MyData>
{
   protected override int GetKeyForItem(MyData item)
   {
      return item.Id;
   }
}

private void Test()
{
   MyData temp, md = new MyData() { Id = 1, Data = "Test" };
   
   // Using a Dictionary
   Dictionary<int, MyData> dict = new Dictionary<int, MyData>();
   dict.Add(md.Id, md);  // Add to dictionary
   temp = dict[1];       // Retrieve

   // Using KeyedCollection
   KeyedCollection<int, MyData> keyd = new MyDataKeyedCollection();
   keyd.Add(md);         // Add to KeyedCollection
   temp = keyd[1];       // Retrieve
}

As you can see, usage is very, very similar to a Dictionary, with the only difference that the Add method only accepts 1 parameter.  Retrieval is exactly the same.  However, since KeyedCollection is an abstract class, you cannot use it directly; you have to derive from it and use your derived class – that’s why I created the MyDataKeyedCollection class.  This MyDataKeyedCollection class has to override the GetKeyForItem method (which is declared as an abstract method in the base class) so you can retrieve the key for the given item.  For me this is somewhat of a deal breaker – I have to always derive from it – there’s no way to use it easily, like a typical collection class.

So my next step is to try to make it easier to consume… thus I created my KeyedCollectionEx class.

public class KeyedCollectionEx<TKey, TItem> : KeyedCollection<TKey, TItem>
{
   private Func<TItem, TKey> _getKeyForItemDelegate;
   public KeyedCollectionEx(Func<TItem, TKey> getKeyForItemDelegate) : base()
   {
      if (getKeyForItemDelegate == null)
         throw new ArgumentNullException("Delegate passed can't be null!");

      _getKeyForItemDelegate = getKeyForItemDelegate;
   }

   protected override TKey GetKeyForItem(TItem item)
   {
      return _getKeyForItemDelegate(item);
   }
}

The constructor now requires a delegate that will get the TKey for the given TItem – I’m using the Func delegate which is in .NET 3.0, so if you’re using .NET 2.0, you need to create your own delegate signature.  With this, my test method becomes as follows:

private void Test2()
{
   MyData temp, md = new MyData() { Id = 1, Data = "Test" };

   // Using KeyedCollectionEx with anonymous delegate
   KeyedCollection<int, MyData> keyd = new KeyedCollectionEx<int, MyData>(delegate(MyData myData) { return myData.Id; });
   keyd.Add(md);         // Add to KeyedCollection
   temp = keyd[1];       // Retrieve

   // Using KeyedCollectionEx with lambda expression
   KeyedCollection<int, MyData> keyd2 = new KeyedCollectionEx<int, MyData>(myData => myData.Id);
   keyd2.Add(md);         // Add to KeyedCollection
   temp = keyd2[1];       // Retrieve
}

I demonstrated how to use it with anonymous methods (so I don’t have to create a method for it), and also how to use it with a lambda expression.  Much simpler, IMHO – no need to create a derived class.  However, I would like this to work with WPF’s data binding – so I’d like further enhance my KeyedCollectionEx class so it can notify WPF when items are being added or removed from it – that’ll be my next post.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Thursday, January 07, 2010 10:42 AM Print
Comments
Gravatar
# re: Using KeyedCollection<TKey, TItem>
nice
9/6/2010 8:11 PM
Good article! I like the Extended keyedCollection. Also I find "reduplicating" to be one of the funnier things I've read in a while. cheers.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
Therapy Programs
11/3/2010 2:27 AM
Thank you for posting. It is an additional information for me. Thanks for the read. Liked it. I'm sure to follow up on your post in the future. Great post.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
Xrystiann Mxyzptlk
11/3/2010 2:29 AM
I would like to thank you for the effort in writing this article. I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
great essays
2/17/2011 11:39 PM
This is really needed to be shared to many readers. Keep on pursuing good things so that you can help many people on their needs suchlike this. You’re a good author.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
Flannel Sheets
3/14/2011 1:21 AM
The KeyedCollection class is a hybrid between a collection based on the IList generic interface and a collection based on the IDictionary generic interface. By default, the KeyedCollection includes a lookup dictionary. Thanks.



Gravatar
# re: Using KeyedCollection<TKey, TItem>
Hosting
3/16/2011 1:20 PM
Been looking for this...! And this is what I searching for ...thanks for sharing the code man... :)
Gravatar
# re: Using KeyedCollection<TKey, TItem>
chore cards
3/18/2011 9:03 PM
I've been involved in a lengthy discussion recently at work involving the I Disposable implementation in WCF clients.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
One24
5/25/2011 5:26 AM
I didn't hear about this before. But Anyways, thanks a lot for posting. I really appreciate it.
Gravatar
# re: Using KeyedCollection<TKey, TItem>
childhood anxiety treatment
2/1/2012 6:09 AM
Thank you so much for sharing this one up. I love this blog.

Post Comment

Title *
Name *
Email
Url
Comment *