Я использовал инкапсуляцию для создания IDictionary с поведением, очень похожим на STL map , для тех из вас, кто знаком с c ++. Для тех, кто не:
- indexer get {} в SafeDictionary ниже возвращает значение по умолчанию, если ключ отсутствует, и добавляет этот ключ в словарь со значением по умолчанию. Это часто желаемое поведение, так как вы ищите предметы, которые в конечном итоге появятся или имеют хорошие шансы появиться.
- метод Add (ключ TK, TV val) ведет себя как метод AddOrUpdate, заменяя текущее значение, если оно существует, а не бросание. Я не понимаю, почему m $ не имеет метода AddOrUpdate и считает, что выбрасывать ошибки в очень распространенных сценариях - хорошая идея.
TL / DR - SafeDictionary написан так, чтобы никогда не генерировать исключения ни при каких обстоятельствах, кроме порочных сценариев , например, из-за того, что на компьютере не хватает памяти (или произошел пожар) , Это достигается путем замены Add на поведение AddOrUpdate и возврата по умолчанию вместо того, чтобы выдавать исключение NotFoundException из индексатора.
Вот код:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class SafeDictionary<TK, TD>: IDictionary<TK, TD> {
Dictionary<TK, TD> _underlying = new Dictionary<TK, TD>();
public ICollection<TK> Keys => _underlying.Keys;
public ICollection<TD> Values => _underlying.Values;
public int Count => _underlying.Count;
public bool IsReadOnly => false;
public TD this[TK index] {
get {
TD data;
if (_underlying.TryGetValue(index, out data)) {
return data;
}
_underlying[index] = default(TD);
return default(TD);
}
set {
_underlying[index] = value;
}
}
public void CopyTo(KeyValuePair<TK, TD>[] array, int arrayIndex) {
Array.Copy(_underlying.ToArray(), 0, array, arrayIndex,
Math.Min(array.Length - arrayIndex, _underlying.Count));
}
public void Add(TK key, TD value) {
_underlying[key] = value;
}
public void Add(KeyValuePair<TK, TD> item) {
_underlying[item.Key] = item.Value;
}
public void Clear() {
_underlying.Clear();
}
public bool Contains(KeyValuePair<TK, TD> item) {
return _underlying.Contains(item);
}
public bool ContainsKey(TK key) {
return _underlying.ContainsKey(key);
}
public IEnumerator<KeyValuePair<TK, TD>> GetEnumerator() {
return _underlying.GetEnumerator();
}
public bool Remove(TK key) {
return _underlying.Remove(key);
}
public bool Remove(KeyValuePair<TK, TD> item) {
return _underlying.Remove(item.Key);
}
public bool TryGetValue(TK key, out TD value) {
return _underlying.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator() {
return _underlying.GetEnumerator();
}
}