示例#1
0
        /// <summary>
        /// Checks to see if the key is present in the dictionary and has
        /// at least one value associated with it.
        /// </summary>
        /// <param name="key">The key to check.</param>
        /// <returns>True if <paramref name="key"/> is present and has at least
        /// one value associated with it. Returns false otherwise.</returns>
        public sealed override bool ContainsKey(TKey key)
        {
            KeyAndValues find = new KeyAndValues(key);
            KeyAndValues temp;

            return(hash.Find(find, false, out temp));
        }
示例#2
0
            /// <summary>
            /// Make a copy of a KeyAndValues, copying the array.
            /// </summary>
            /// <param name="x">KeyAndValues to copy.</param>
            /// <returns>A copied version.</returns>
            public static KeyAndValues Copy(KeyAndValues x)
            {
                KeyAndValues result;

                result.Key   = x.Key;
                result.Count = x.Count;

                result.Values = (x.Values != null) ? (TValue[])x.Values.Clone() : null;

                return(result);
            }
示例#3
0
        /// <summary>
        ///  Enumerate the values in the a KeyAndValues structure. Can't return
        /// the array directly because:
        ///   a) The array might be larger than the count.
        ///   b) We can't allow clients to down-cast to the array and modify it.
        ///   c) We have to abort enumeration if the hash changes.
        /// </summary>
        /// <param name="keyAndValues">Item with the values to enumerate..</param>
        /// <returns>An enumerable that enumerates the items in the KeyAndValues structure.</returns>
        private IEnumerator <TValue> EnumerateValues(KeyAndValues keyAndValues)
        {
            int count = keyAndValues.Count;
            int stamp = hash.GetEnumerationStamp();

            for (int i = 0; i < count; ++i)
            {
                yield return(keyAndValues.Values[i]);

                hash.CheckEnumerationStamp(stamp);
            }
        }
示例#4
0
        /// <summary>
        ///  Enumerate the values in the a KeyAndValues structure. Can't return
        /// the array directly because:
        ///   a) The array might be larger than the count.
        ///   b) We can't allow clients to down-cast to the array and modify it.
        ///   c) We have to abort enumeration if the hash changes.
        /// </summary>
        /// <param name="keyAndValues">Item with the values to enumerate..</param>
        /// <returns>An enumerable that enumerates the items in the KeyAndValues structure.</returns>
        private IEnumerator <TValue> EnumerateValues(KeyAndValues keyAndValues)
        {
            var count = keyAndValues.Count;
            var stamp = _hash.GetEnumerationStamp();

            for (var i = 0; i < count; ++i)
            {
                yield return(keyAndValues.Values[i]);

                _hash.CheckEnumerationStamp(stamp);
            }
        }
示例#5
0
        /// <summary>
        /// Removes a given value from the values associated with a key. If the
        /// last value is removed from a key, the key is removed also.
        /// </summary>
        /// <param name="key">A key to remove a value from.</param>
        /// <param name="value">The value to remove.</param>
        /// <returns>True if <paramref name="value"/> was associated with <paramref name="key"/> (and was
        /// therefore removed). False if <paramref name="value"/> was not associated with <paramref name="key"/>.</returns>
        public sealed override bool Remove(TKey key, TValue value)
        {
            KeyAndValues keyValues = new KeyAndValues(key);
            KeyAndValues existing;

            if (hash.Find(keyValues, false, out existing))
            {
                // There is an item in the hash table equal to this key. Find the value.
                int existingCount = existing.Count;
                int valueHash     = Util.GetHashCode(value, valueEqualityComparer);
                int indexFound    = -1;
                for (int i = 0; i < existingCount; ++i)
                {
                    if (Util.GetHashCode(existing.Values[i], valueEqualityComparer) == valueHash &&
                        valueEqualityComparer.Equals(existing.Values[i], value))
                    {
                        // Found an equal existing value
                        indexFound = i;
                    }
                }

                if (existingCount == 1)
                {
                    // Removing the last value. Remove the key.
                    hash.Delete(existing, out keyValues);
                    return(true);
                }
                else if (indexFound >= 0)
                {
                    // Found a value. Remove it.
                    if (indexFound < existingCount - 1)
                    {
                        Array.Copy(existing.Values, indexFound + 1, existing.Values, indexFound, existingCount - indexFound - 1);
                    }
                    existing.Count = existingCount - 1;

                    // Update the hash.
                    hash.Find(existing, true, out keyValues);
                    return(true);
                }
                else
                {
                    // Value was not found.
                    return(false);
                }
            }
            else
            {
                return(false);         // key not found.
            }
        }
示例#6
0
        /// <summary>
        /// <para>Adds a new value to be associated with a key. If duplicate values are permitted, this
        /// method always adds a new key-value pair to the dictionary.</para>
        /// <para>If duplicate values are not permitted, and <paramref name="key"/> already has a value
        /// equal to <paramref name="value"/> associated with it, then that value is replaced with <paramref name="value"/>,
        /// and the number of values associate with <paramref name="key"/> is unchanged.</para>
        /// </summary>
        /// <param name="key">The key to associate with.</param>
        /// <param name="value">The value to associated with <paramref name="key"/>.</param>
        public sealed override void Add(TKey key, TValue value)
        {
            KeyAndValues keyValues = new KeyAndValues(key);
            KeyAndValues existing;

            if (hash.Find(keyValues, false, out existing))
            {
                // There already is an item in the hash table equal to this key. Add the new value,
                // taking into account duplicates if needed.
                int existingCount = existing.Count;
                if (!allowDuplicateValues)
                {
                    int valueHash = Util.GetHashCode(value, valueEqualityComparer);
                    for (int i = 0; i < existingCount; ++i)
                    {
                        if (Util.GetHashCode(existing.Values[i], valueEqualityComparer) == valueHash &&
                            valueEqualityComparer.Equals(existing.Values[i], value))
                        {
                            // Found an equal existing value. Replace it and we're done.
                            existing.Values[i] = value;
                            return;
                        }
                    }
                }

                // Add a new value to an existing key.
                if (existingCount == existing.Values.Length)
                {
                    // Grow the array to make room.
                    TValue[] newValues = new TValue[existingCount * 2];
                    Array.Copy(existing.Values, newValues, existingCount);
                    existing.Values = newValues;
                }
                existing.Values[existingCount] = value;
                existing.Count = existingCount + 1;

                // Update the hash table.
                hash.Find(existing, true, out keyValues);
                return;
            }
            else
            {
                // No item with this key. Add it.
                keyValues.Count  = 1;
                keyValues.Values = new TValue[1] {
                    value
                };
                hash.Insert(keyValues, true, out existing);
                return;
            }
        }
示例#7
0
        /// <summary>
        /// Gets the number of values associated with a given key.
        /// </summary>
        /// <param name="key">The key to count values of.</param>
        /// <returns>The number of values associated with <paramref name="key"/>. If <paramref name="key"/>
        /// is not present in the dictionary, zero is returned.</returns>
        protected sealed override int CountValues(TKey key)
        {
            KeyAndValues find = new KeyAndValues(key);
            KeyAndValues item;

            if (hash.Find(find, false, out item))
            {
                return(item.Count);
            }
            else
            {
                return(0);
            }
        }
示例#8
0
        /// <summary>
        /// Determines if this dictionary contains a key equal to <paramref name="key"/>. If so, all the values
        /// associated with that key are returned through the values parameter.
        /// </summary>
        /// <param name="key">The key to search for.</param>
        /// <param name="values">Returns all values associated with key, if true was returned.</param>
        /// <returns>True if the dictionary contains key. False if the dictionary does not contain key.</returns>
        protected sealed override bool TryEnumerateValuesForKey(TKey key, out IEnumerator <TValue> values)
        {
            KeyAndValues find = new KeyAndValues(key);
            KeyAndValues item;

            if (hash.Find(find, false, out item))
            {
                values = EnumerateValues(item);
                return(true);
            }
            else
            {
                values = null;
                return(false);
            }
        }
示例#9
0
            /// <summary>
            /// Make a copy of a KeyAndValues, copying the array.
            /// </summary>
            /// <param name="x">KeyAndValues to copy.</param>
            /// <returns>A copied version.</returns>
            public static KeyAndValues Copy(KeyAndValues x)
            {
                KeyAndValues result;

                result.Key   = x.Key;
                result.Count = x.Count;

                if (x.Values != null)
                {
                    result.Values = (TValue[])x.Values.Clone();
                }
                else
                {
                    result.Values = null;
                }

                return(result);
            }
示例#10
0
        /// <summary>
        /// Checks to see if <paramref name="value"/> is associated with <paramref name="key"/>
        /// in the dictionary.
        /// </summary>
        /// <param name="key">The key to check.</param>
        /// <param name="value">The value to check.</param>
        /// <returns>True if <paramref name="value"/> is associated with <paramref name="key"/>.</returns>
        public sealed override bool Contains(TKey key, TValue value)
        {
            KeyAndValues find = new KeyAndValues(key);
            KeyAndValues item;

            if (hash.Find(find, false, out item))
            {
                int existingCount = item.Count;
                int valueHash     = Util.GetHashCode(value, valueEqualityComparer);
                for (int i = 0; i < existingCount; ++i)
                {
                    if (Util.GetHashCode(item.Values[i], valueEqualityComparer) == valueHash &&
                        valueEqualityComparer.Equals(item.Values[i], value))
                    {
                        // Found an equal existing value.
                        return(true);
                    }
                }
            }

            return(false);
        }