Exemple #1
0
        /// <summary>
        /// Makes a deep clone of this bag. A new bag is created with a clone of
        /// each element of this bag, by calling ICloneable.Clone on each element. If T is
        /// a value type, then each element is copied as if by simple assignment.
        /// </summary>
        /// <remarks><para>If T is a reference type, it must implement
        /// ICloneable. Otherwise, an InvalidOperationException is thrown.</para>
        /// <para>Cloning the bag takes time O(N log N), where N is the number of items in the bag.</para></remarks>
        /// <returns>The cloned bag.</returns>
        /// <exception cref="InvalidOperationException">T is a reference type that does not implement ICloneable.</exception>
        public Bag <T> CloneContents()
        {
            bool itemIsValueType;

            if (!CollectionUtil.IsCloneableType(typeof(T), out itemIsValueType))
            {
                throw new InvalidOperationException(string.Format(Strings.TypeNotCloneable, typeof(T).FullName));
            }

            Hash <KeyValuePair <T, int> > newHash = new Hash <KeyValuePair <T, int> >(equalityComparer);

            // Clone each item, and add it to the new ordered bag.
            foreach (KeyValuePair <T, int> pair in hash)
            {
                KeyValuePair <T, int> newPair, dummy;
                T newKey;

                if (!itemIsValueType && pair.Key != null)
                {
                    newKey = (T)(((ICloneable)pair.Key).Clone());
                }
                else
                {
                    newKey = pair.Key;
                }

                newPair = NewPair(newKey, pair.Value);

                newHash.Insert(newPair, true, out dummy);
            }

            return(new Bag <T>(equalityComparer, keyEqualityComparer, newHash, count));
        }
Exemple #2
0
        /// <summary>
        /// Makes a deep clone of this set. A new set is created with a clone of
        /// each element of this set, by calling ICloneable.Clone on each element. If T is
        /// a value type, then each element is copied as if by simple assignment.
        /// </summary>
        /// <remarks><para>If T is a reference type, it must implement
        /// ICloneable. Otherwise, an InvalidOperationException is thrown.</para>
        /// <para>Cloning the set takes time O(N), where N is the number of items in the set.</para></remarks>
        /// <returns>The cloned set.</returns>
        /// <exception cref="InvalidOperationException">T is a reference type that does not implement ICloneable.</exception>
        public Set <T> CloneContents()
        {
            bool itemIsValueType;

            if (!CollectionUtil.IsCloneableType(typeof(T), out itemIsValueType))
            {
                throw new InvalidOperationException(string.Format(Strings.TypeNotCloneable, typeof(T).FullName));
            }

            Set <T> clone = new Set <T>(equalityComparer);

            // Clone each item, and add it to the new ordered set.
            foreach (T item in this)
            {
                T itemClone;

                if (itemIsValueType)
                {
                    itemClone = item;
                }
                else
                {
                    if (item == null)
                    {
                        itemClone = default(T);    // Really null, because we know T is a reference type
                    }
                    else
                    {
                        itemClone = (T)(((ICloneable)item).Clone());
                    }
                }

                clone.Add(itemClone);
            }

            return(clone);
        }
Exemple #3
0
        /// <summary>
        /// Makes a deep clone of this dictionary. A new dictionary is created with a clone of
        /// each entry of this dictionary, by calling ICloneable.Clone on each element. If TKey or TValue is
        /// a value type, then each element is copied as if by simple assignment.
        /// </summary>
        /// <remarks><para>If TKey or TValue is a reference type, it must implement
        /// ICloneable. Otherwise, an InvalidOperationException is thrown.</para>
        /// <para>Cloning the dictionary takes time O(N log N), where N is the number of key-value pairs in the dictionary.</para></remarks>
        /// <returns>The cloned dictionary.</returns>
        /// <exception cref="InvalidOperationException">TKey or TValue is a reference type that does not implement ICloneable.</exception>
        public MultiDictionary <TKey, TValue> CloneContents()
        {
            bool keyIsValueType, valueIsValueType;

            // Make sure that TKey and TValue can be cloned.
            if (!CollectionUtil.IsCloneableType(typeof(TKey), out keyIsValueType))
            {
                NonCloneableType(typeof(TKey));
            }

            if (!CollectionUtil.IsCloneableType(typeof(TValue), out valueIsValueType))
            {
                NonCloneableType(typeof(TValue));
            }

            // It's tempting to do a more efficient cloning, utilizing the hash.Clone() method. However, we can't know that
            // the cloned version of the key has the same hash value.

            MultiDictionary <TKey, TValue> newDict = new MultiDictionary <TKey, TValue>(allowDuplicateValues, keyEqualityComparer, valueEqualityComparer);

            foreach (KeyAndValues item in hash)
            {
                // Clone the key and values parts. Value types can be cloned
                // by just copying them, otherwise, ICloneable is used.
                TKey     keyClone;
                TValue[] valuesClone;

                if (keyIsValueType)
                {
                    keyClone = item.Key;
                }
                else
                {
                    if (item.Key == null)
                    {
                        keyClone = default(TKey);  // Really null, because we know TKey isn't a value type.
                    }
                    else
                    {
                        keyClone = (TKey)(((ICloneable)item.Key).Clone());
                    }
                }

                valuesClone = new TValue[item.Count];
                if (valueIsValueType)
                {
                    Array.Copy(item.Values, valuesClone, item.Count);
                }
                else
                {
                    for (int i = 0; i < item.Count; ++i)
                    {
                        if (item.Values[i] == null)
                        {
                            valuesClone[i] = default(TValue);   // Really null, because we know TKey isn't a value type.
                        }
                        else
                        {
                            valuesClone[i] = (TValue)(((ICloneable)item.Values[i]).Clone());
                        }
                    }
                }

                newDict.AddMany(keyClone, valuesClone);
            }

            return(newDict);
        }