Created
February 15, 2018 19:58
-
-
Save mstum/0763fe7cec30582e5c5c878482018410 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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