/// <summary>
            /// Adds the specified key.
            /// </summary>
            /// <param name="key">The key to add.</param>
            /// <param name="value">The value to add.</param>
            /// <param name="keyOnlyComparer">The key comparer.</param>
            /// <param name="valueComparer">The value comparer.</param>
            /// <param name="behavior">The intended behavior for certain cases that may come up during the operation.</param>
            /// <param name="result">A description of the effect was on adding an element to this <see cref="HashBucket"/>.</param>
            /// <returns>A new <see cref="HashBucket"/> that contains the added value and any values already held by this <see cref="HashBucket"/>.</returns>
            internal HashBucket Add(TKey key, TValue value, IEqualityComparer <KeyValuePair <TKey, TValue> > keyOnlyComparer, IEqualityComparer <TValue> valueComparer, KeyCollisionBehavior behavior, out OperationResult result)
            {
                var kv = new KeyValuePair <TKey, TValue>(key, value);

                if (this.IsEmpty)
                {
                    result = OperationResult.SizeChanged;
                    return(new HashBucket(kv));
                }

                if (keyOnlyComparer.Equals(kv, _firstValue))
                {
                    switch (behavior)
                    {
                    case KeyCollisionBehavior.SetValue:
                        result = OperationResult.AppliedWithoutSizeChange;
                        return(new HashBucket(kv, _additionalElements));

                    case KeyCollisionBehavior.Skip:
                        result = OperationResult.NoChangeRequired;
                        return(this);

                    case KeyCollisionBehavior.ThrowIfValueDifferent:
                        if (!valueComparer.Equals(_firstValue.Value, value))
                        {
                            throw new ArgumentException(SR.Format(SR.DuplicateKey, key));
                        }

                        result = OperationResult.NoChangeRequired;
                        return(this);

                    case KeyCollisionBehavior.ThrowAlways:
                        throw new ArgumentException(SR.Format(SR.DuplicateKey, key));

                    default:
                        throw new InvalidOperationException();     // unreachable
                    }
                }

                int keyCollisionIndex = _additionalElements.IndexOf(kv, keyOnlyComparer);

                if (keyCollisionIndex < 0)
                {
                    result = OperationResult.SizeChanged;
                    return(new HashBucket(_firstValue, _additionalElements.Add(kv)));
                }
                else
                {
                    switch (behavior)
                    {
                    case KeyCollisionBehavior.SetValue:
                        result = OperationResult.AppliedWithoutSizeChange;
                        return(new HashBucket(_firstValue, _additionalElements.ReplaceAt(keyCollisionIndex, kv)));

                    case KeyCollisionBehavior.Skip:
                        result = OperationResult.NoChangeRequired;
                        return(this);

                    case KeyCollisionBehavior.ThrowIfValueDifferent:
                        ref readonly var existingEntry = ref _additionalElements.ItemRef(keyCollisionIndex);
            /// <summary>
            /// Adds the specified value.
            /// </summary>
            /// <param name="value">The value.</param>
            /// <param name="valueComparer">The value comparer.</param>
            /// <param name="result">A description of the effect was on adding an element to this <see cref="HashBucket"/>.</param>
            /// <returns>A new <see cref="HashBucket"/> that contains the added value and any values already held by this <see cref="HashBucket"/>.</returns>
            internal HashBucket Add(T value, IEqualityComparer <T> valueComparer, out OperationResult result)
            {
                if (this.IsEmpty)
                {
                    result = OperationResult.SizeChanged;
                    return(new HashBucket(value));
                }

                if (valueComparer.Equals(value, _firstValue) || _additionalElements.IndexOf(value, valueComparer) >= 0)
                {
                    result = OperationResult.NoChangeRequired;
                    return(this);
                }

                result = OperationResult.SizeChanged;
                return(new HashBucket(_firstValue, _additionalElements.Add(value)));
            }