I\'m basically looking for a way to access a hashtable value using a two-dimensional typed key in c#.
Eventually I would be able to do something like this
I'd suggest a slight variation on jachymko's solution which will allow you to avoid creating a class for key pairs. Instead, wrap a private dictionary of dictionaries, as so:
public class MultiDictionary<K1, K2, V>
{
private Dictionary<K1, Dictionary<K2, V>> dict =
new Dictionary<K1, Dictionary<K2, V>>();
public V this[K1 key1, K2 key2]
{
get
{
return dict[key1][key2];
}
set
{
if (!dict.ContainsKey(key1))
{
dict[key1] = new Dictionary<K2, V>();
}
dict[key1][key2] = value;
}
}
}
I think this might be closer to what you're looking for...
var data = new Dictionary<int, Dictionary<bool, int>>();
You need a key class for the Dictonary
that implements GetHashCode
correctly.
And you can extend Dictonary
to let you access it in a friendly way.
The KeyPair
class:
public class KeyPair<Tkey1, Tkey2>
{
public KeyPair(Tkey1 key1, Tkey2 key2)
{
Key1 = key1;
Key2 = key2;
}
public Tkey1 Key1 { get; set; }
public Tkey2 Key2 { get; set; }
public override int GetHashCode()
{
return Key1.GetHashCode() ^ Key2.GetHashCode();
}
public override bool Equals(object obj)
{
KeyPair<Tkey1, Tkey2> o = obj as KeyPair<Tkey1, Tkey2>;
if (o == null)
return false;
else
return Key1.Equals(o.Key1) && Key2.Equals(o.Key2);
}
}
Extend Dictonary<>
:
public class KeyPairDictonary<Tkey1, Tkey2, Tvalue>
: Dictionary<KeyPair<Tkey1, Tkey2>, Tvalue>
{
public Tvalue this[Tkey1 key1, Tkey2 key2]
{
get
{
return this[new KeyPair<Tkey1, Tkey2>(key1, key2)];
}
set
{
this[new KeyPair<Tkey1, Tkey2>(key1, key2)] = value;
}
}
}
You can use it like this:
KeyPairDictonary<int, bool, string> dict =
new KeyPairDictonary<int, bool, string>();
dict[1, false] = "test";
string test = dict[1, false];
Wrap your two-dimensional key in a separate type
and use that type as a key. Also consider overriding GetHashCode()
and Equals()
methods. Preferably use Dictionary<>
instead of HashTable
since apparently you can use that.
You can do this in C# 7.0 now with the new tuples:
// Declare
var test = new Dictionary<(int, bool), int>();
// Add
test.Add((1, false), 5);
// Get
int a = test[(1, false)];
Just in case anyone is here recently, an example of how to do this the quick and dirty way in .Net 4.0, as described by one of the commenters.
class Program
{
static void Main(string[] args)
{
var twoDic = new Dictionary<Tuple<int, bool>, String>();
twoDic.Add(new Tuple<int, bool>(3, true), "3 and true." );
twoDic.Add(new Tuple<int, bool>(4, true), "4 and true." );
twoDic.Add(new Tuple<int, bool>(3, false), "3 and false.");
// Will throw exception. Item with the same key already exists.
// twoDic.Add(new Tuple<int, bool>(3, true), "3 and true." );
Console.WriteLine(twoDic[new Tuple<int, bool>(3,false)]);
Console.WriteLine(twoDic[new Tuple<int, bool>(4,true)]);
// Outputs "3 and false." and "4 and true."
}
}