oleksii
6/1/2017 - 8:44 PM

DefaultDictionary.cs

using System;
using System.Collections;
using System.Collections.Generic;

public class DefaultDictionary<TKey, TValue>: IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>
{
    private readonly Dictionary<TKey, TValue> _dictionary;

    public Func<TKey, TValue> ValueFactory { get; }

    #region Factory constructors

    public DefaultDictionary(Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        ValueFactory = valueFactory;
    }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary, Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        _dictionary = new Dictionary<TKey, TValue>(dictionary);
        ValueFactory = valueFactory;
    }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer, Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        _dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
        ValueFactory = valueFactory;
    }

    public DefaultDictionary(IEqualityComparer<TKey> comparer, Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        _dictionary = new Dictionary<TKey, TValue>(comparer);
        ValueFactory = valueFactory;
    }

    public DefaultDictionary(int capacity, Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        _dictionary = new Dictionary<TKey, TValue>(capacity);
        ValueFactory = valueFactory;
    }

    public DefaultDictionary(int capacity, IEqualityComparer<TKey> comparer, Func<TKey, TValue> valueFactory)
    {
        if (valueFactory == null) throw new ArgumentNullException(nameof(valueFactory));

        _dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
        ValueFactory = valueFactory;
    }

    #endregion

    #region Value constructors

    public DefaultDictionary(TValue value): this(_ => value) { }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary, TValue value): this(dictionary, _ => value) { }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer, TValue value): this(dictionary, comparer,
        _ => value) { }

    public DefaultDictionary(IEqualityComparer<TKey> comparer, TValue value): this(comparer, _ => value) { }

    public DefaultDictionary(int capacity, TValue value): this(capacity, _ => value) { }

    public DefaultDictionary(int capacity, IEqualityComparer<TKey> comparer, TValue value): this(capacity, comparer, _ => value) { }

    #endregion

    #region Dictionary constructors

    public DefaultDictionary(): this(default(TValue)) { }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary): this(dictionary, default(TValue)) { }

    public DefaultDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer):
        this(dictionary, comparer, default(TValue)) { }

    public DefaultDictionary(IEqualityComparer<TKey> comparer): this(comparer, default(TValue)) { }

    public DefaultDictionary(int capacity): this(capacity, default(TValue)) { }

    public DefaultDictionary(int capacity, IEqualityComparer<TKey> comparer): this(capacity, comparer, default(TValue)) { }

    #endregion

    #region Implementation of IEnumerable

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _dictionary.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable) _dictionary).GetEnumerator();
    }

    #endregion

    #region Implementation of ICollection<KeyValuePair<TKey,TValue>>

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).Add(item);
    }

    public void Clear()
    {
        ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).CopyTo(array, arrayIndex);
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).Remove(item);
    }

    public int Count => ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).Count;

    public bool IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>) _dictionary).IsReadOnly;

    #endregion

    #region Implementation of IDictionary<TKey,TValue>

    public void Add(TKey key, TValue value)
    {
        _dictionary.Add(key, value);
    }

    public bool ContainsKey(TKey key)
    {
        return _dictionary.ContainsKey(key);
    }

    public bool Remove(TKey key)
    {
        return _dictionary.Remove(key);
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        if (_dictionary.TryGetValue(key, out value)) return true;

        value = ValueFactory(key);
        return false;
    }

    public TValue this[TKey key]
    {
        get
        {
            TValue value;
            TryGetValue(key, out value);
            return value;
        }
        set { _dictionary[key] = value; }
    }

    IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => _dictionary.Keys;

    IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => _dictionary.Values;

    public ICollection<TKey> Keys => _dictionary.Keys;

    public ICollection<TValue> Values => _dictionary.Values;

    #endregion

}