File: System\Data\Common\Utils\KeyToListMap.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
// <copyright file="KeyToListMap.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// @owner Microsoft
// @backupOwner Microsoft
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Collections.ObjectModel;
namespace System.Data.Common.Utils {
    // This class contains an abstraction that map a key of type TKey to a
    // list of values (of type TValue). This is really a convenience abstraction
    internal class KeyToListMap<TKey, TValue> : InternalBase {
        #region Constructors
        // effects: Creates an empty map with keys compared using comparer
        internal KeyToListMap(IEqualityComparer<TKey> comparer) {
            Debug.Assert(null != comparer);
            m_map = new Dictionary<TKey, List<TValue>>(comparer);
        #region Fields
        // Just a regular dictionary
        private Dictionary<TKey, List<TValue>> m_map;
        #region Properties
        // effects: Yields all the keys in this
        internal IEnumerable<TKey> Keys {
            get { return m_map.Keys; }
        // effects: Returns all the values for all keys with all the values
        // of a particular key adjacent to each other
        internal IEnumerable<TValue> AllValues {
            get {
                foreach (TKey key in Keys) {
                    foreach (TValue value in ListForKey(key)) {
                        yield return value;
        // effects: Returns all the Dictionary Entries in this Map.
        internal IEnumerable<KeyValuePair<TKey, List<TValue>>> KeyValuePairs {
            get {
                return m_map;
        #region Methods
        internal bool ContainsKey(TKey key) {
            return m_map.ContainsKey(key);
        // effects: Adds <key, value> to this. If the entry already exists, another one is added
        internal void Add(TKey key, TValue value) {
            // If entry for key already exists, add value to the list, else
            // create a new list and add the value to it
            List<TValue> valueList;
            if (!m_map.TryGetValue(key, out valueList)) {
                valueList = new List<TValue>();
                m_map[key] = valueList;
        // effects: Adds <key, value> for each value in values to this. If the entry already exists, another one is added
        internal void AddRange(TKey key, IEnumerable<TValue> values) {
            foreach (TValue value in values) {
                Add(key, value);
        // effects: Removes all entries corresponding to key
        // Returns true iff the key was removed
        internal bool RemoveKey(TKey key) {
            return m_map.Remove(key);
        // requires: key exist in this
        // effects: Returns the values associated with key
        internal System.Collections.ObjectModel.ReadOnlyCollection<TValue> ListForKey(TKey key) {
            Debug.Assert(m_map.ContainsKey(key), "key not registered in map");
            return new System.Collections.ObjectModel.ReadOnlyCollection<TValue>(m_map[key]);
        // effects: Returns true if the key exists and false if not.
        //          In case the Key exists, the out parameter is assigned the List for that key,
        //          otherwise it is assigned a null value
        internal bool TryGetListForKey(TKey key, out System.Collections.ObjectModel.ReadOnlyCollection<TValue> valueCollection)
            List<TValue> list;
            valueCollection = null;
            if (m_map.TryGetValue(key, out list))
                valueCollection = new System.Collections.ObjectModel.ReadOnlyCollection<TValue>(list);
                return true;
            return false;
        // Returns all values for the given key. If no values have been added for the key,
        // yields no values.
        internal IEnumerable<TValue> EnumerateValues(TKey key) {
            List<TValue> values;
            if (m_map.TryGetValue(key, out values)) {
                foreach (TValue value in values) { yield return value; }
        internal override void ToCompactString(StringBuilder builder) {
            foreach (TKey key in Keys) {
                // Calling key's ToString here
                StringUtil.FormatStringBuilder(builder, "{0}", key);
                builder.Append(": ");
                IEnumerable<TValue> values = ListForKey(key);
                StringUtil.ToSeparatedString(builder, values, ",", "null");
                builder.Append("; ");