Вы всегда можете свернуть свой словарь.
Решение 1: Наследуйте и используйте «новые» методы переопределения, сначала проверяющие наличие ключа. Если да, верните это значение с помощью ключа или создайте на
Func<K, T>
делегат. Тем не менее, это решение будет перерыв при использовании этого словаря через интерфейс
IDictionary<K,T>
Так что вы должны быть более тщательно с помощью раствора 2.
Решение 2: Словарь обертка, которая использует внутренний словарь - остальное то же самое, что и решение 1.
Решение 3: ConcurrentDictionary предлагает GetOrAdd, который также является потокобезопасным.
Решение 4: ConcurrentDictionary Упаковочный аналогично решению 2.
Вот словарь обертка:
public class WrappedDictionary<K, T> : IDictionary<K, T>
{
public IDictionary<K, T> WrappedInstance { get; set; }
public virtual T this[K key]
{
get
{
// CUSTOM RESOLUTION CODE GOES HERE
return this.WrappedInstance[key];
}
set
{
this.WrappedInstance[key] = value;
}
}
public int Count
{
get
{
return this.WrappedInstance.Count;
}
}
public bool IsReadOnly
{
get
{
return this.WrappedInstance.IsReadOnly;
}
}
public ICollection<K> Keys
{
get
{
return this.WrappedInstance.Keys;
}
}
public ICollection<T> Values
{
get
{
return this.WrappedInstance.Values;
}
}
public void Add(KeyValuePair<K, T> item)
{
this.WrappedInstance.Add(item);
}
public void Add(K key, T value)
{
this.WrappedInstance.Add(key, value);
}
public void Clear()
{
this.WrappedInstance.Clear();
}
public bool Contains(KeyValuePair<K, T> item)
{
return this.WrappedInstance.Contains(item);
}
public bool ContainsKey(K key)
{
return this.WrappedInstance.ContainsKey(key);
}
public void CopyTo(KeyValuePair<K, T>[] array, int arrayIndex)
{
this.WrappedInstance.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<K, T>> GetEnumerator()
{
return this.WrappedInstance.GetEnumerator();
}
public bool Remove(KeyValuePair<K, T> item)
{
return this.WrappedInstance.Remove(item);
}
public bool Remove(K key)
{
return this.WrappedInstance.Remove(key);
}
public bool TryGetValue(K key, out T value)
{
// CUSTOM RESOLUTION CODE GOES HERE
return this.WrappedInstance.TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.WrappedInstance.GetEnumerator();
}
}
Просто заметка о вашем упоминании используя значение создателя. Это имеет большее значение, когда либо создание значения дорого, либо обычный случай НЕ является созданием новых экземпляров. Если вы используете только типы значений или путем профилирования, вы обнаружите, что общий случай создает новые экземпляры, это может быть больше накладных расходов, чем необходимо, поэтому лучше использовать назначение прямых значений и общие делегаты. Существуют также случаи, когда вы хотите назначить уже созданное значение. – Jeremy