Created
June 29, 2016 12:47
-
-
Save Pzixel/01cce08812dda273a0d41b5bdaa3a7e0 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
public class NullableDictionary<TKey, TValue> : IDictionary<TKey?, TValue> where TKey : struct | |
{ | |
private bool _hasNull; | |
private TValue _nullKeyValue; | |
private readonly Dictionary<TKey, TValue> _dictionary; | |
public NullableDictionary(): this(0, null) { } | |
public NullableDictionary(int capacity): this(capacity, null) { } | |
public NullableDictionary(IEqualityComparer<TKey> comparer): this(0, comparer) { } | |
public NullableDictionary(int capacity, IEqualityComparer<TKey> comparer) | |
{ | |
_dictionary = new Dictionary<TKey, TValue>(capacity, comparer); | |
} | |
public NullableDictionary(IDictionary<TKey, TValue> dictionary): this(dictionary, null) { } | |
public NullableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) : | |
this(dictionary?.Count ?? 0, comparer) | |
{ | |
if (dictionary == null) | |
{ | |
throw new ArgumentNullException(nameof(dictionary)); | |
} | |
foreach (var pair in dictionary) | |
{ | |
Add(pair.Key, pair.Value); | |
} | |
} | |
public IEnumerator<KeyValuePair<TKey?, TValue>> GetEnumerator() | |
{ | |
if (_hasNull) | |
yield return new KeyValuePair<TKey?, TValue>(null, _nullKeyValue); | |
foreach (var pair in _dictionary) | |
{ | |
yield return new KeyValuePair<TKey?, TValue>(pair.Key, pair.Value); | |
} | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return ((IEnumerable) _dictionary).GetEnumerator(); | |
} | |
public void Add(KeyValuePair<TKey?, TValue> item) | |
{ | |
Add(item.Key, item.Value); | |
} | |
public void Clear() | |
{ | |
_hasNull = false; | |
_nullKeyValue = default(TValue); | |
_dictionary.Clear(); | |
} | |
public bool Contains(KeyValuePair<TKey?, TValue> item) | |
{ | |
if (!item.Key.HasValue) | |
{ | |
return _hasNull; | |
} | |
return _dictionary.Contains(new KeyValuePair<TKey, TValue>(item.Key.GetValueOrDefault(), item.Value)); | |
} | |
public void CopyTo(KeyValuePair<TKey?, TValue>[] array, int arrayIndex) | |
{ | |
foreach (var pair in this) | |
{ | |
array[arrayIndex++] = pair; | |
} | |
} | |
public bool Remove(KeyValuePair<TKey?, TValue> item) | |
{ | |
if (!item.Key.HasValue) | |
{ | |
var hadNull = _hasNull; | |
_hasNull = false; | |
return hadNull; | |
} | |
return _dictionary.Remove(item.Key.GetValueOrDefault()); | |
} | |
public int Count => _hasNull ? _dictionary.Count + 1 : _dictionary.Count; | |
public bool IsReadOnly => false; | |
public bool ContainsKey(TKey? key) | |
{ | |
if (!key.HasValue) | |
{ | |
return _hasNull; | |
} | |
return _dictionary.ContainsKey(key.GetValueOrDefault()); | |
} | |
public void Add(TKey? key, TValue value) | |
{ | |
if (!key.HasValue) | |
{ | |
if (_hasNull) | |
{ | |
throw new ArgumentException("Dictionary already has a null key value pair"); | |
} | |
_hasNull = true; | |
_nullKeyValue = value; | |
} | |
else | |
{ | |
_dictionary.Add(key.GetValueOrDefault(), value); | |
} | |
} | |
public bool Remove(TKey? key) | |
{ | |
if (!key.HasValue) | |
{ | |
bool hadNull = _hasNull; | |
_hasNull = false; | |
return hadNull; | |
} | |
return _dictionary.Remove(key.GetValueOrDefault()); | |
} | |
public bool TryGetValue(TKey? key, out TValue value) | |
{ | |
if (!key.HasValue) | |
{ | |
value = _nullKeyValue; | |
return _hasNull; | |
} | |
return _dictionary.TryGetValue(key.GetValueOrDefault(), out value); | |
} | |
public TValue this[TKey? key] | |
{ | |
get | |
{ | |
if (!key.HasValue) | |
{ | |
if (_hasNull) | |
{ | |
return _nullKeyValue; | |
} | |
throw new KeyNotFoundException(); | |
} | |
return _dictionary[key.GetValueOrDefault()]; | |
} | |
set { Add(key, value); } | |
} | |
public ICollection<TKey?> Keys => this.Select(x => x.Key).ToList(); | |
public ICollection<TValue> Values => this.Select(x => x.Value).ToList(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment