Skip to content

Instantly share code, notes, and snippets.

@JohnLBevan
Created March 16, 2018 23:28
Show Gist options
  • Select an option

  • Save JohnLBevan/eaa313821bb54ef545ed3b764fa6f599 to your computer and use it in GitHub Desktop.

Select an option

Save JohnLBevan/eaa313821bb54ef545ed3b764fa6f599 to your computer and use it in GitHub Desktop.
Bidirectional generic dictionary; used for simple 1:1 mappings. Just holds 2 dictionaries 1 key,value the other value,key. Probably a better solution exists, but this meets my needs.
using System;
using System.Collections;
using System.Collections.Generic;
namespace JohnLBevan.Collections.Generic
{
public class BidirectionalDictionary<T1, T2>: IDictionary<T1, T2>
{
IDictionary<T1, T2> ab;
IDictionary<T2, T1> ba;
public BidirectionalDictionary()
{
ab = new Dictionary<T1, T2>();
ba = new Dictionary<T2, T1>();
}
public void Add(T1 key, T2 value)
{
AssertNotInDictionary(key, value);
ab.Add(key, value);
ba.Add(value, key);
}
public T2 this[T1 key]
{
get => ab[key];
set {
AssertNotInDictionary(key, value);
ab[key] = value;
ba[value] = key;
}
}
public ICollection<T1> Keys => ab.Keys;
public ICollection<T2> Values => ab.Values;
public int Count => ab.Count;
public bool IsReadOnly => ab.IsReadOnly;
public void Add(KeyValuePair<T1, T2> item) => Add(item.Key, item.Value);
public void Clear()
{
ab.Clear();
ba.Clear();
}
public bool Contains(KeyValuePair<T1, T2> item) => ab.Contains(item);
public bool ContainsKey(T1 key) => ab.ContainsKey(key);
public bool ContainsValue(T2 value) => ba.ContainsKey(value);
public void CopyTo(KeyValuePair<T1, T2>[] array, int arrayIndex) => ab.CopyTo(array, arrayIndex);
public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator() => ab.GetEnumerator();
public bool Remove(T1 key)
{
ab.TryGetValue(key, out T2 value);
return ab.Remove(key) && ba.Remove(value);
}
public bool Remove2(T2 key)
{
ba.TryGetValue(key, out T1 value);
return ba.Remove(key) && ab.Remove(value);
}
public bool Remove(KeyValuePair<T1, T2> item) => ab.Remove(item) && ba.Remove(item.Value);
public bool TryGetValue(T1 key, out T2 value) => ab.TryGetValue(key, out value);
public bool TryGetValue2(T2 key, out T1 value) => ba.TryGetValue(key, out value);
IEnumerator IEnumerable.GetEnumerator() => ab.GetEnumerator();
const string ElementAlreadyExistsExceptionMessage = "An element with the same key already exists. {0}";
const string ParameterNameKey = "key";
const string ParameterNameValue = "value";
private void AssertNotInDictionary(T1 key, T2 value)
{
if (ab.ContainsKey(key)) throw new ArgumentException(string.Format(ElementAlreadyExistsExceptionMessage,key), ParameterNameKey);
if (ba.ContainsKey(value)) throw new ArgumentException(string.Format(ElementAlreadyExistsExceptionMessage,value), ParameterNameValue);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment