Is there a dictionary available in .NET
that could hold 2 keys and one value.
Like
Dictionary(Of TKey, Of TKey, TValue)
I have
Here's something better in terms of efficiency.
public class MultiKeyDictionary<TKeyType1, TKeyType2, TValueType>
{
private readonly object threadLock = new object();
private readonly Dictionary<TKeyType1, TValueType> _dictionary1 = new Dictionary<TKeyType1, TValueType>();
private readonly Dictionary<TKeyType2, TValueType> _dictionary2 = new Dictionary<TKeyType2, TValueType>();
private readonly Dictionary<TKeyType1, TKeyType2> _Key1Key2Map = new Dictionary<TKeyType1, TKeyType2>();
private readonly Dictionary<TKeyType2, TKeyType1> _Key2Key1Map = new Dictionary<TKeyType2, TKeyType1>();
public bool Add(TKeyType1 key1, TKeyType2 key2, TValueType v)
{
if (ContainsKey1(key1) || ContainsKey2(key2))
return false;
_dictionary1.Add(key1, v);
_dictionary2.Add(key2, v);
_Key1Key2Map.Add(key1, key2);
_Key2Key1Map.Add(key2, key1);
return true;
}
public bool ContainsKey1(TKeyType1 key)
{
return _dictionary1.ContainsKey(key);
}
public bool ContainsKey2(TKeyType2 key)
{
return _dictionary2.ContainsKey(key);
}
//Note if TKeyType1 and TKeyType2 are the same then we are forced to use GetBy functions
public TValueType GetByKey1(TKeyType1 key)
{
return _dictionary1[key];
}
public TValueType GetByKey2(TKeyType2 key)
{
return _dictionary2[key];
}
public bool SetByKey1(TKeyType1 key, TValueType val)
{
if (ContainsKey1(key))
return false;
lock (threadLock)
{
var key2 = _Key1Key2Map[key];
_dictionary1[key] = val;
_dictionary2[key2] = val;
}
return true;
}
public bool SetByKey2(TKeyType2 key, TValueType val)
{
if (ContainsKey2(key))
return false;
lock (threadLock)
{
var key1 = _Key2Key1Map[key];
_dictionary1[key1] = val;
_dictionary2[key] = val;
}
return true;
}
public void RemoveUsingKey1(TKeyType1 key)
{
lock (threadLock)
{
var key2 = _Key1Key2Map[key];
_dictionary1.Remove(key);
_dictionary2.Remove(key2);
_Key1Key2Map.Remove(key);
_Key2Key1Map.Remove(key2);
}
}
public void RemoveUsingKey2(TKeyType2 key)
{
lock (threadLock)
{
var key1 = _Key2Key1Map[key];
_dictionary1.Remove(key1);
_dictionary2.Remove(key);
_Key1Key2Map.Remove(key1);
_Key2Key1Map.Remove(key);
}
}
public bool Contains(TKeyType1 key)
{
return _dictionary1.ContainsKey(key);
}
public bool Contains(TKeyType2 key)
{
return _dictionary2.ContainsKey(key);
}
public TValueType this[TKeyType1 key]
{
get => GetByKey1(key);
set => SetByKey1(key, value);
}
public TValueType this[TKeyType2 key]
{
get => GetByKey2(key);
set => SetByKey2(key, value);
}
public void Remove(TKeyType1 key)
{
RemoveUsingKey1(key);
}
public void Remove(TKeyType2 key)
{
RemoveUsingKey2(key);
}
public int Count => _dictionary1.Count;
public Dictionary<TKeyType1, TValueType>.KeyCollection Key1s => _dictionary1.Keys;
public Dictionary<TKeyType2, TValueType>.KeyCollection Key2s => _dictionary2.Keys;
public Dictionary<TKeyType1, TValueType>.ValueCollection Values => _dictionary1.Values;
public void Clear()
{
lock (threadLock)
{
_dictionary1.Clear();
_dictionary2.Clear();
_Key1Key2Map.Clear();
_Key2Key1Map.Clear();
}
}
//Map between Keys
public TKeyType2 Key2(TKeyType1 key)
{
return _Key1Key2Map[key];
}
public TKeyType1 Key1(TKeyType2 key)
{
return _Key2Key1Map[key];
}
}