Last active
May 24, 2019 02:28
-
-
Save TheBuzzSaw/f7bee52a3445510d3b188d5d8f2326c7 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.Generic; | |
namespace Kelly | |
{ | |
public class TwoWayDictionary<TKey, TValue> : IDictionary<TKey, TValue> | |
{ | |
private readonly Dictionary<TKey, TValue> _main; | |
private readonly Dictionary<TValue, TKey> _reverse; | |
private IDictionary<TKey, TValue> IMain => _main as IDictionary<TKey, TValue>; | |
private IDictionary<TValue, TKey> IReverse => _reverse as IDictionary<TValue, TKey>; | |
public TwoWayDictionary<TValue, TKey> Reverse { get; } | |
ICollection<TKey> IDictionary<TKey, TValue>.Keys => IMain.Keys; | |
ICollection<TValue> IDictionary<TKey, TValue>.Values => IMain.Values; | |
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => IMain.IsReadOnly; | |
public int Count => _main.Count; | |
public Dictionary<TKey, TValue>.KeyCollection Keys => _main.Keys; | |
public Dictionary<TKey, TValue>.ValueCollection Values => _main.Values; | |
public TValue this[TKey key] | |
{ | |
get => _main[key]; | |
set | |
{ | |
bool hadOldValue = _main.Remove(key, out var oldValue); | |
if (hadOldValue) | |
_reverse.Remove(oldValue); | |
bool hadOldKey = _reverse.Remove(value, out var oldKey); | |
if (hadOldKey) | |
_main.Remove(oldKey); | |
try | |
{ | |
Add(key, value); | |
} | |
catch | |
{ | |
if (hadOldKey) | |
Add(oldKey, value); | |
if (hadOldValue) | |
Add(key, oldValue); | |
throw; | |
} | |
} | |
} | |
public TwoWayDictionary() | |
{ | |
_main = new Dictionary<TKey, TValue>(); | |
_reverse = new Dictionary<TValue, TKey>(); | |
Reverse = new TwoWayDictionary<TValue, TKey>(this); | |
} | |
private TwoWayDictionary(TwoWayDictionary<TValue, TKey> reverse) | |
{ | |
Reverse = reverse; | |
_main = reverse._reverse; | |
_reverse = reverse._main; | |
} | |
public void Add(TKey key, TValue value) | |
{ | |
_main.Add(key, value); | |
try | |
{ | |
_reverse.Add(value, key); | |
} | |
catch | |
{ | |
_main.Remove(key); | |
throw; | |
} | |
} | |
public bool ContainsKey(TKey key) => _main.ContainsKey(key); | |
public bool ContainsValue(TValue value) => _reverse.ContainsKey(value); | |
public bool Remove(TKey key) | |
{ | |
if (_main.Remove(key, out var value)) | |
{ | |
_reverse.Remove(value); | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
public bool TryGetValue(TKey key, out TValue value) => _main.TryGetValue(key, out value); | |
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) | |
{ | |
IMain.Add(item); | |
try | |
{ | |
var pair = KeyValuePair.Create(item.Value, item.Key); | |
IReverse.Add(pair); | |
} | |
catch | |
{ | |
IMain.Remove(item); | |
throw; | |
} | |
} | |
public void Clear() | |
{ | |
_main.Clear(); | |
_reverse.Clear(); | |
} | |
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) => | |
IMain.Contains(item); | |
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => | |
IMain.CopyTo(array, arrayIndex); | |
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) | |
{ | |
if (IMain.Remove(item)) | |
{ | |
var pair = KeyValuePair.Create(item.Value, item.Key); | |
IReverse.Remove(pair); | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
public Dictionary<TKey, TValue>.Enumerator GetEnumerator() => | |
_main.GetEnumerator(); | |
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => | |
IMain.GetEnumerator(); | |
IEnumerator IEnumerable.GetEnumerator() => (_main as IEnumerable).GetEnumerator(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment