Skip to content

Instantly share code, notes, and snippets.

@mstum
Created February 15, 2018 19:58
Show Gist options
  • Save mstum/0763fe7cec30582e5c5c878482018410 to your computer and use it in GitHub Desktop.
Save mstum/0763fe7cec30582e5c5c878482018410 to your computer and use it in GitHub Desktop.
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
/// <summary>
/// Wrapper for Two Dictionaries to allow lookup by Key or by Value.
/// Note that Value can't ever be null, as Dictionary will throw on a null Key.
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class DoubleKeyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private IDictionary<TKey, TValue> _keyToValue;
private IDictionary<TValue, TKey> _valueToKey;
public DoubleKeyDictionary() : this(new Dictionary<TKey, TValue>(), new Dictionary<TValue, TKey>())
{
}
protected DoubleKeyDictionary(IDictionary<TKey, TValue> keyToValueDict, IDictionary<TValue, TKey> valueToKeyDict)
{
_keyToValue = keyToValueDict ?? throw new ArgumentNullException(nameof(keyToValueDict));
_valueToKey = valueToKeyDict ?? throw new ArgumentNullException(nameof(valueToKeyDict));
}
public TValue this[TKey key] {
get => _keyToValue[key];
set
{
_keyToValue[key] = value;
_valueToKey[value] = key;
}
}
public bool ContainsValue(TValue value) => _valueToKey.ContainsKey(value);
public TKey GetKeyForValue(TValue value) => _valueToKey[value];
public ICollection<TKey> Keys => _keyToValue.Keys;
public ICollection<TValue> Values => _valueToKey.Keys;
public int Count => _keyToValue.Count;
public bool IsReadOnly => false;
public void Add(TKey key, TValue value) => this[key] = value;
public void Add(KeyValuePair<TKey, TValue> item) => this[item.Key] = item.Value;
public void Clear()
{
_keyToValue.Clear();
_valueToKey.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
=> _keyToValue.Contains(item);
public bool ContainsKey(TKey key)
=> _keyToValue.ContainsKey(key);
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
=> _keyToValue.CopyTo(array, arrayIndex);
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
=> _keyToValue.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
public bool Remove(TKey key)
{
if (!ContainsKey(key))
{
return false;
}
var value = _keyToValue[key];
_keyToValue.Remove(key);
_valueToKey.Remove(value);
return true;
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
if (!ContainsKey(item.Key))
{
return false;
}
if (EqualityComparer<TValue>.Default.Equals(_keyToValue[item.Key], item.Value))
{
_keyToValue.Remove(item.Key);
_valueToKey.Remove(item.Value);
return true;
}
return false;
}
public bool TryGetValue(TKey key, out TValue value) => _keyToValue.TryGetValue(key, out value);
}
public sealed class ConcurrentDoubleKeyDictionary<TKey, TValue> : DoubleKeyDictionary<TKey, TValue>
{
public ConcurrentDoubleKeyDictionary() : base(new ConcurrentDictionary<TKey, TValue>(), new ConcurrentDictionary<TValue, TKey>())
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment