読者です 読者をやめる 読者になる 読者になる

一対多の Dictionary が欲しい

.net

1つのキーに複数の値を関連付けたいケースは結構あるのに、.NET Framework のクラスライブラリには該当するクラスがありません。これはちょっと不便。

Dictionary> を使うという手がありますが、この方法は使い勝手が悪いです。結局、次のようなクラスを用意することになります。

public class MultiDictionary<TKey, TValue> : IDictionary<TKey, List<TValue>>
{
    private Dictionary<TKey, List<TValue>> _dic;

    public MultiDictionary()
    {
        _dic = new Dictionary<TKey, List<TValue>>();
    }

    public void Add(TKey key, TValue value)
    {
        if (!_dic.ContainsKey(key))
        {
            _dic.Add(key, new List<TValue>());
        }
        _dic[key].Add(value);
    }

    #region IEnumerable メンバ

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

    #endregion

    #region IEnumerable<T> メンバ

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

    #endregion

    #region ICollection<T> メンバ

    public int Count
    {
        get { return _dic.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public void Add(KeyValuePair<TKey, List<TValue>> pair)
    {
        foreach (TValue value in pair.Value)
        {
            Add(pair.Key, value);
        }
    }

    public bool Remove(KeyValuePair<TKey, List<TValue>> pair)
    {
        // 面倒なので、キーと値を全部消しちゃえ
        return Remove(pair.Key);
    }

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

    public void Clear()
    {
        _dic.Clear();
    }

    public bool Contains(KeyValuePair<TKey, List<TValue>> pair)
    {
        return _dic.Contains(pair);
    }

    #endregion

    #region IDictionary<TKey, TValue> メンバ

    public List<TValue> this[TKey key]
    {
        get { return _dic[key]; }
        set { _dic[key] = value; }
    }

    public ICollection<TKey> Keys
    {
        get { return _dic.Keys; }
    }

    public ICollection<List<TValue>> Values
    {
        get { return _dic.Values; }
    }

    public void Add(TKey key, List<TValue> values)
    {
        foreach (TValue value in values)
        {
            Add(key, value);
        }
    }

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

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

    public bool TryGetValue(TKey key, out List<TValue> value)
    {
        return _dic.TryGetValue(key, out value);
    }

    #endregion
}

勢いで書いたので、簡単なテストしか行っていません。注意。

標準で用意してくれないかなぁ。