BradVin's .Net Blog

Code, snippets, controls, utils, etc. Basically all things .net

December 2007 - Posts

 √úberUtils Series posts so far :

I figured it was about time I did another post in the UberUtils series seeing that I haven't written a post in over a month. So here is the next installment. This time it's for collections. I hear you asking "but the framework has every collection I will ever need", and this is true for 98% of the time. But every once in a while there comes a time where I find myself subtly changing the way an existing collection works, or wishing it could do something just slightly differently. As with any software development, there are many different ways to solve the same problem, so you probably find yourself getting around limitations with the built-in collections without even knowing it. (I know I have when I go back and look at code I've written).

The number one question I have found myself asking over the years with regards to the collection namespace is:

Is there a dictionary whereby I can access the values from both the key and an index?

The answer to this is NO. And if I'm wrong about this then please shoot me now for wasting so much time over the years on this code. You can overcome this limitation by using the other collections at your disposal, and with not so much code either. The thing is, I hate writing the same code over and over again (I actually refuse to do it), so why not write a generic dictionary that can access the values by index? And then just use that dictionary instead of the normal dictionary in the future.

Introducing the IndexedDictionary, an indexable dictionary. Here is a unit test to show the indexing feature :

        [TestMethod()]
public void SomeTest()
{
IndexedDictionary<string, int> col = new IndexedDictionary<string,int>();
col.Add("1", 1);
col.Add("2", 2);
col.AddAt(0, "0", 0); //add by index
col.Add("3", 3);
col.RemoveAt(2); //remove by index
string strList = string.Empty;
for (int i = 0; i < col.Count; i++)
{
strList += col[i]; //get by index
}
Assert.AreEqual(strList, "013");
}
As you can see, you can access the dictionary now by an index (aswell as your key). This is accomplished simply by inheriting from the Dictionary class and holding a List inside the class too :
    public class IndexedDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
protected List<TKey> m_col = new List<TKey>();

I have also added some extra features which can be toggled :

  • Replace Duplicate Keys - obviously you cannot have multiple entries in a dictionary with the same key, so what this does instead is replaces a value with the same key when adding to the collection
  • Throw Error On Invalid Remove - if disabled, when you try to remove an item that does not exist in the collection it just does nothing and does not throw an exception as it normally does

Immediately after this new collection came the NamedIndexedDictionary. This is a sub class of the IndexedDictionary class that takes a string as the key.

public class NamedIndexedDictionary<TValue> : IndexedDictionary<string, TValue>

The string key can also be set to be case insensitive or not, so calling col["abc"] is the same as col["ABC"].

Both have been very useful to me in the past and I hope someone else will find them useful too. Send me any other helpful collections you have created and I will add them too. 

Download here : collections.zip

 

Posted by bradvin | 5 comment(s)
Filed under: , , ,
More Posts