At one point during my application I came across the need to have three string keys for an instance of a class (I am using C# 3.5, so I couldn't use a tuple). By looking online, I came across this answer whose code I used: https://stackoverflow.com/a/15804355/5090537
After tailoring its bits and pieces for my needs, in the end my custom class looked like this:
public class MultiKeyDictionary<K1, K2, K3, V> : Dictionary<K1, MultiKeyDictionary<K2, K3, V>>
{
public V this[K1 key1, K2 key2, K3 key3]
{
get
{
return ContainsKey(key1) ? this[key1][key2, key3] : default(V);
}
set
{
if (!ContainsKey(key1))
this[key1] = new MultiKeyDictionary<K2, K3, V>();
this[key1][key2, key3] = value;
}
}
public bool ContainsKey(K1 key1, K2 key2, K3 key3)
{
return base.ContainsKey(key1) && this[key1].ContainsKey(key2, key3);
}
public void Add(K1 key1, K2 key2, K3 key3, V value)
{
if (!ContainsKey(key1))
this[key1] = new MultiKeyDictionary<K2, K3, V>();
if (!this[key1].ContainsKey(key2, key3))
this[key1][key2] = new Dictionary<K3, V>();
this[key1][key2][key3] = value;
}
}
This worked great for my needs but I have a few questions on this data structure:
1) Since I am actually inheriting from a Dictionary(K1, Dictionary(K2, V))
, is it correct to assume that GetHashCode
is implemented for me and I don't need to specify a separate implementation? And the same for Equals?
2) Is also the premise that I needed to create my own custom class correct? Since I couldn't use a string array or string list for example, because then there would be a ReferenceEquals
comparison instead of the memberwise comparison that I needed (key1 equal to key1, key2 equal to key2, and key3 equal to key3)?