예제 #1
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     = CollectionUtil.GetHashCode(value, valueEqualityComparer);
                int indexFound    = -1;
                for (int i = 0; i < existingCount; ++i)
                {
                    if (CollectionUtil.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.
            }
        }
예제 #2
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 = CollectionUtil.GetHashCode(value, valueEqualityComparer);
                    for (int i = 0; i < existingCount; ++i)
                    {
                        if (CollectionUtil.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;
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the full hash code for an item.
        /// </summary>
        /// <param name="item">Item to get hash code for.</param>
        /// <returns>The full hash code. It is never zero.</returns>
        private int GetFullHash(T item)
        {
            uint hash;

            hash = (uint)CollectionUtil.GetHashCode(item, equalityComparer);

            // The .NET framework tends to produce pretty bad hash codes.
            // Scramble them up to be much more random!
            hash += ~(hash << 15);
            hash ^= (hash >> 10);
            hash += (hash << 3);
            hash ^= (hash >> 6);
            hash += ~(hash << 11);
            hash ^= (hash >> 16);
            hash &= 0x7FFFFFFF;
            if (hash == 0)
            {
                hash = 0x7FFFFFFF;     // Make sure it isn't zero.
            }
            return((int)hash);
        }
예제 #4
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     = CollectionUtil.GetHashCode(value, valueEqualityComparer);
                for (int i = 0; i < existingCount; ++i)
                {
                    if (CollectionUtil.GetHashCode(item.Values[i], valueEqualityComparer) == valueHash &&
                        valueEqualityComparer.Equals(item.Values[i], value))
                    {
                        // Found an equal existing value.
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #5
0
 public int GetHashCode(KeyAndValues obj)
 {
     return(CollectionUtil.GetHashCode(obj.Key, keyEqualityComparer));
 }
예제 #6
0
 public int GetHashCode(KeyValuePair <TKey, TValue> obj)
 {
     return(CollectionUtil.GetHashCode(obj.Key, keyEqualityComparer));
 }