/// <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)); }
/// <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); }
/// <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); } }
/// <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); } }
/// <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. } }
/// <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; } }
/// <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); } }
/// <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); } }
/// <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); }
/// <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); }