The other day I needed to have a dictionary (i.e. fast search by key) class that works on two keys.  This is somewhat akin to a three level tree structure -- first level has elements specified by first key, second level – by second key, and the final third level are the actual data nodes.

 

Below is the code that does just that (disclaimer – this was created in about 15 min… no real testing, yet… use at your own risk!)

 

[Serializable]

public class NestedDictionary<TKey, TKey2, TValue> : Dictionary<TKey, Dictionary<TKey2, TValue>>

{

    public void Add(TKey key1, TKey2 key2, TValue value)

    {

        if (base.ContainsKey(key1) == false)

            base.Add(key1, new Dictionary<TKey2, TValue>());

 

        base[key1].Add(key2, value);

    }

 

    public TValue this[TKey key1, TKey2 key2]

    {

        get

        {

            TValue result = default(TValue);

 

            if (base.ContainsKey(key1) == true)

            {

                if (base[key1].ContainsKey(key2) == true)

                    result = base[key1][key2];

            }

 

            return result;

        }

        set

        {

            if (base.ContainsKey(key1) == false)

                base.Add(key1, new Dictionary<TKey2, TValue>());

 

            if (base[key1].ContainsKey(key2) == false)

                base[key1][key2] = value;

            else

                base[key1].Add(key2, value);

        }

    }

 

    public virtual bool Remove(TKey key1, TKey2 key2)

    {

        bool result = false;

 

        if (base.ContainsKey(key1) == true)

        {

            if (base[key1].ContainsKey(key2) == true)

                result = base[key1].Remove(key2);

        }

 

        return result;

    }

 

    public TKey[] FirstLevelKeys()

    {

        List<TKey> result = new List<TKey>();

        result.AddRange(base.Keys);

        return result.ToArray();

    }

 

    public TKey2[] SecondLevelKeys(TKey key1)

    {

        List<TKey2> result = new List<TKey2>();

        if (base.ContainsKey(key1) == true)

            result.AddRange(base[key1].Keys);

        return result.ToArray();

    }

}