`
阿尔萨斯
  • 浏览: 4188159 次
社区版块
存档分类
最新评论

C# - OrderedDictionary<TKey, TValue> Implementation

 
阅读更多

There is no OrderedDictionary<TKey, TValue> in .net framework, let's implement one for use.

namespace CSharpLearning
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;

    /// <summary>
    /// Represents a generic collection of key/value pairs that are ordered independently of the key and value.
    /// </summary>
    /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
    /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
    public class OrderedDictionary<TKey, TValue> : IOrderedDictionary<TKey, TValue>
    {
        #region Fields

        /// <summary>
        /// The default initial capacity.
        /// </summary>
        private const int DefaultInitialCapacity = 0;

        /// <summary>
        /// The key type name.
        /// </summary>
        private static readonly string KeyTypeName = typeof(TKey).FullName;

        /// <summary>
        /// The value type name.
        /// </summary>
        private static readonly string ValueTypeName = typeof(TValue).FullName;

        /// <summary>
        /// Is value type a reference type.
        /// </summary>
        private static readonly bool IsValueTypeReferenceType = !typeof(ValueType).IsAssignableFrom(typeof(TValue));

        /// <summary>
        /// The dictionary.
        /// </summary>
        private Dictionary<TKey, TValue> dictionary;

        /// <summary>
        /// The list.
        /// </summary>
        private List<KeyValuePair<TKey, TValue>> list;

        /// <summary>
        /// The comparer.
        /// </summary>
        private IEqualityComparer<TKey> comparer;

        /// <summary>
        /// The sync root.
        /// </summary>
        private object syncRoot;

        /// <summary>
        /// The initial capacity.
        /// </summary>
        private int initialCapacity;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}"/> class. 
        /// </summary>
        public OrderedDictionary()
            : this(DefaultInitialCapacity)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}"/> class using the specified comparer. 
        /// </summary>
        /// <param name="comparer">
        /// The <see cref="IEqualityComparer{TKey}"> IEqualityComparer<TKey> </see> to use when comparing keys, or <null/> to use the default <see cref="EqualityComparer{TKey}"> EqualityComparer<TKey> </see> for the type of the key.
        /// </param>
        public OrderedDictionary(IEqualityComparer<TKey> comparer)
            : this(DefaultInitialCapacity, comparer)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}"/> class using the specified initial capacity and comparer.
        /// </summary>
        /// <param name="capacity">
        /// The initial number of elements that the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection can contain.
        /// </param>
        /// <param name="comparer">
        /// The <see cref="IEqualityComparer{TKey}"> IEqualityComparer<TKey> </see> to use when comparing keys, or <null/> to use the default <see cref="EqualityComparer{TKey}"> EqualityComparer<TKey> </see> for the type of the key.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="capacity"/> is less than 0.
        /// </exception>
        public OrderedDictionary(int capacity, IEqualityComparer<TKey> comparer = null)
        {
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException("capacity", "'capacity' must be non-negative.");
            }

            this.initialCapacity = capacity;
            this.comparer = comparer;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets a value indicating whether the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection is read-only.
        /// </summary>
        /// <value><see langword="true"/> if the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is read-only; otherwise, <see langword="false"/>. The default is <see langword="false"/>.</value>
        /// <remarks>
        /// A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
        /// <para>A collection that is read-only is simply a collection with a wrapper that prevents modification of the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes.</para>
        /// </remarks>
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an <see cref="System.Collections.Generic.ICollection{TKey}"> ICollection<TKey> </see> object containing the keys in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.
        /// </summary>
        /// <value>An <see cref="System.Collections.Generic.ICollection{TKey}"> ICollection<TKey> </see> object containing the keys in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</value>
        /// <remarks>The returned <see cref="System.Collections.Generic.ICollection{TKey}"> ICollection<TKey> </see> object is not a static copy; instead, the collection refers back to the keys in the original <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>. Therefore, changes to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> continue to be reflected in the key collection.</remarks>
        public ICollection<TKey> Keys
        {
            get
            {
                return this.Dictionary.Keys;
            }
        }

        /// <summary>
        /// Gets an <see cref="ICollection{TValue}"> ICollection<TValue> </see> object containing the values in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.
        /// </summary>
        /// <value>An <see cref="ICollection{TValue}"> ICollection<TValue> </see> object containing the values in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</value>
        /// <remarks>The returned <see cref="ICollection{TValue}"> ICollection<TKey> </see> object is not a static copy; instead, the collection refers back to the values in the original <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>. Therefore, changes to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> continue to be reflected in the value collection.</remarks>
        public ICollection<TValue> Values
        {
            get
            {
                return this.Dictionary.Values;
            }
        }

        /// <summary>
        /// Gets the number of key/values pairs contained in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <value>The number of key/value pairs contained in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.</value>
        public int Count
        {
            get
            {
                return this.List.Count;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> has a fixed size.
        /// </summary>
        /// <value><see langword="true"/> if the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> has a fixed size; otherwise, <see langword="false"/>. The default is <see langword="false"/>.</value>
        bool IDictionary.IsFixedSize
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an <see cref="ICollection"/> object containing the keys in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.
        /// </summary>
        /// <value>An <see cref="ICollection"/> object containing the keys in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</value>
        /// <remarks>The returned <see cref="ICollection"/> object is not a static copy; instead, the collection refers back to the keys in the original <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>. Therefore, changes to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> continue to be reflected in the key collection.</remarks>
        ICollection IDictionary.Keys
        {
            get
            {
                return (ICollection)this.Keys;
            }
        }

        /// <summary>
        /// Gets an <see cref="ICollection"/> object containing the values in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <value>An <see cref="ICollection"/> object containing the values in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.</value>
        /// <remarks>The returned <see cref="ICollection"/> object is not a static copy; instead, the <see cref="ICollection"/> refers back to the values in the original <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection. Therefore, changes to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> continue to be reflected in the <see cref="ICollection"/>.</remarks>
        ICollection IDictionary.Values
        {
            get
            {
                return (ICollection)this.Values;
            }
        }

        /// <summary>
        /// Gets a value indicating whether access to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> object is synchronized (thread-safe).
        /// </summary>
        /// <value>This method always returns false.</value>
        bool ICollection.IsSynchronized
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an object that can be used to synchronize access to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> object.
        /// </summary>
        /// <value>An object that can be used to synchronize access to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> object.</value>
        object ICollection.SyncRoot
        {
            get
            {
                if (this.syncRoot == null)
                {
                    System.Threading.Interlocked.CompareExchange(ref this.syncRoot, new object(), null);
                }

                return this.syncRoot;
            }
        }

        /// <summary>
        /// Gets the dictionary object that stores the keys and values.
        /// </summary>
        /// <value>The dictionary object that stores the keys and values for the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</value>
        /// <remarks>Accessing this property will create the dictionary object if necessary.</remarks>
        private Dictionary<TKey, TValue> Dictionary
        {
            get
            {
                if (null == this.dictionary)
                {
                    this.dictionary = new Dictionary<TKey, TValue>(this.initialCapacity, this.comparer);
                }

                return this.dictionary;
            }
        }

        /// <summary>
        /// Gets the list object that stores the key/value pairs.
        /// </summary>
        /// <value>The list object that stores the key/value pairs for the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</value>
        /// <remarks>Accessing this property will create the list object if necessary.</remarks>
        private List<KeyValuePair<TKey, TValue>> List
        {
            get
            {
                if (null == this.list)
                {
                    this.list = new List<KeyValuePair<TKey, TValue>>(this.initialCapacity);
                }

                return this.list;
            }
        }

        #endregion

        #region Indexers

        /// <summary>
        /// Gets or sets the value at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the value to get or set.</param>
        /// <returns>The value of the item at the specified index.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
        /// -or-<br/>
        /// Index is equal to or greater than <see cref="Count"/>.</exception>
        public TValue this[int index]
        {
            get
            {
                return this.List[index].Value;
            }

            set
            {
                if (index >= this.Count || index < 0)
                {
                    throw new ArgumentOutOfRangeException("index", "'index' must be non-negative and less than the size of the collection.");
                }

                TKey key = this.List[index].Key;
                this.List[index] = new KeyValuePair<TKey, TValue>(key, value);
                this.Dictionary[key] = value;
            }
        }

        /// <summary>
        /// Gets or sets the value with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value associated with the specified key. If the specified key is not found, attempting to get it returns <null/>, and attempting to set it creates a new element using the specified key.</returns>
        public TValue this[TKey key]
        {
            get
            {
                return this.Dictionary[key];
            }

            set
            {
                if (this.Dictionary.ContainsKey(key))
                {
                    this.Dictionary[key] = value;
                    this.List[this.IndexOfKey(key)] = new KeyValuePair<TKey, TValue>(key, value);
                }
                else
                {
                    this.Add(key, value);
                }
            }
        }

        /// <summary>
        /// Gets or sets the value at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the value to get or set.</param>
        /// <returns>The value of the item at the specified index.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
        /// -or-<br/>
        /// Index is equal to or greater than <see cref="Count"/>.</exception>
        object IOrderedDictionary.this[int index]
        {
            get
            {
                return this[index];
            }

            set
            {
                this[index] = ConvertToValueType(value);
            }
        }

        /// <summary>
        /// Gets or sets the value with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get or set.</param>
        /// <returns>The value associated with the specified key. If the specified key is not found, attempting to get it returns <null/>, and attempting to set it creates a new element using the specified key.</returns>
        object IDictionary.this[object key]
        {
            get
            {
                return this[ConvertToKeyType(key)];
            }

            set
            {
                this[ConvertToKeyType(key)] = ConvertToValueType(value);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Adds an entry with the specified key and value into the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection with the lowest available index.
        /// </summary>
        /// <param name="key">The key of the entry to add.</param>
        /// <param name="value">The value of the entry to add. This value can be <null/>.</param>
        /// <returns>The index of the newly added entry.</returns>
        /// <remarks>A key cannot be <null/>, but a value can be.
        /// <para>You can also use the <see cref="OrderedDictionary{TKey,TValue}.Item(TKey)"/> property to add new elements by setting the value of a key that does not exist in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection; however, if the specified key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>, setting the <see cref="OrderedDictionary{TKey,TValue}.Item(TKey)"/> property overwrites the old value. In contrast, the <see cref="Add"/> method does not modify existing elements.</para></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
        /// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</exception>
        public int Add(TKey key, TValue value)
        {
            this.Dictionary.Add(key, value);
            this.List.Add(new KeyValuePair<TKey, TValue>(key, value));
            return this.Count - 1;
        }

        /// <summary>
        /// Removes the entry with the specified key from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <param name="key">The key of the entry to remove.</param>
        /// <returns><see langword="true"/> if the key was found and the corresponding element was removed; otherwise, <see langword="false"/>.</returns>
        public bool Remove(TKey key)
        {
            if (null == key)
            {
                throw new ArgumentNullException("key");
            }

            int index = this.IndexOfKey(key);
            if (index >= 0)
            {
                if (this.Dictionary.Remove(key))
                {
                    this.List.RemoveAt(index);
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Inserts a new entry into the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection with the specified key and value at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which the element should be inserted.</param>
        /// <param name="key">The key of the entry to add.</param>
        /// <param name="value">The value of the entry to add. The value can be <null/> if the type of the values in the dictionary is a reference type.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
        /// -or-<br/>
        /// <paramref name="index"/> is greater than <see cref="Count"/>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
        /// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</exception>
        public void Insert(int index, TKey key, TValue value)
        {
            if (index > this.Count || index < 0)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            this.Dictionary.Add(key, value);
            this.List.Insert(index, new KeyValuePair<TKey, TValue>(key, value));
        }

        /// <summary>
        /// Removes the entry at the specified index from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <param name="index">The zero-based index of the entry to remove.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
        /// -or-<br/>
        /// Index is equal to or greater than <see cref="Count"/>.</exception>
        public void RemoveAt(int index)
        {
            if (index >= this.Count || index < 0)
            {
                throw new ArgumentOutOfRangeException("index", "'index' must be non-negative and less than the size of the collection.");
            }

            TKey key = this.List[index].Key;
            this.List.RemoveAt(index);
            this.Dictionary.Remove(key);
        }

        /// <summary>
        /// Removes all elements from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <remarks>The capacity is not changed as a result of calling this method.</remarks>
        public void Clear()
        {
            this.Dictionary.Clear();
            this.List.Clear();
        }

        /// <summary>
        /// Determines whether the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection contains a specific key.
        /// </summary>
        /// <param name="key">The key to locate in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.</param>
        /// <returns><see langword="true"/> if the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
        public bool ContainsKey(TKey key)
        {
            return this.Dictionary.ContainsKey(key);
        }

        /// <summary>
        /// Returns the zero-based index of the specified key in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.
        /// </summary>
        /// <param name="key">The key to locate in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</param>
        /// <returns>The zero-based index of <paramref name="key"/>, if <paramref name="key"/> is found in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>; otherwise, -1.</returns>
        /// <remarks>This method performs a linear search; therefore it has a cost of O(n) at worst.</remarks>
        public int IndexOfKey(TKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            for (int index = 0; index < this.List.Count; index++)
            {
                KeyValuePair<TKey, TValue> entry = this.List[index];
                TKey next = entry.Key;
                if (null != this.comparer)
                {
                    if (this.comparer.Equals(next, key))
                    {
                        return index;
                    }
                }
                else if (next.Equals(key))
                {
                    return index;
                }
            }

            return -1;
        }

        /// <summary>
        /// Gets the value associated with the specified key.
        /// </summary>
        /// <param name="key">The key of the value to get.</param>
        /// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found; otherwise, the default value for the type of <paramref name="value"/>. This parameter can be passed uninitialized.</param>
        /// <returns><see langword="true"/> if the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            return this.Dictionary.TryGetValue(key, out value);
        }

        /// <summary>
        /// The IOrderedDictionary.GetEnumerator() implementation.
        /// </summary>
        /// <returns>
        /// The <see cref="IDictionaryEnumerator"/>.
        /// </returns>
        IDictionaryEnumerator IOrderedDictionary.GetEnumerator()
        {
            return this.Dictionary.GetEnumerator();
        }

        /// <summary>
        /// The IDictionary.GetEnumerator() implementation.
        /// </summary>
        /// <returns>
        /// The <see cref="IDictionaryEnumerator"/>.
        /// </returns>
        IDictionaryEnumerator IDictionary.GetEnumerator()
        {
            return this.Dictionary.GetEnumerator();
        }

        /// <summary>
        /// The IEnumerable.GetEnumerator() implementation.
        /// </summary>
        /// <returns>
        /// The <see cref="IEnumerator"/>.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.List.GetEnumerator();
        }

        /// <summary>
        /// The IEnumerable<out T>.GetEnumerator() implementation.
        /// </summary>
        /// <returns>
        /// The <see cref="IEnumerator"/>.
        /// </returns>
        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
        {
            return this.List.GetEnumerator();
        }

        /// <summary>
        /// Inserts a new entry into the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection with the specified key and value at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which the element should be inserted.</param>
        /// <param name="key">The key of the entry to add.</param>
        /// <param name="value">The value of the entry to add. The value can be <null/> if the type of the values in the dictionary is a reference type.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
        /// -or-<br/>
        /// <paramref name="index"/> is greater than <see cref="Count"/>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.<br/>
        /// -or-<br/>
        /// <paramref name="value"/> is <null/>, and the value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is a value type.</exception>
        /// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="key"/>.<br/>
        /// -or-<br/>
        /// The value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="value"/>.<br/>
        /// -or-<br/>
        /// An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</exception>
        void IOrderedDictionary.Insert(int index, object key, object value)
        {
            this.Insert(index, ConvertToKeyType(key), ConvertToValueType(value));
        }

        /// <summary>
        /// Adds an entry with the specified key and value into the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection with the lowest available index.
        /// </summary>
        /// <param name="key">The key of the entry to add.</param>
        /// <param name="value">The value of the entry to add. This value can be <null/>.</param>
        /// <remarks>A key cannot be <null/>, but a value can be.
        /// <para>You can also use the <see cref="OrderedDictionary{TKey,TValue}.Item(TKey)"/> property to add new elements by setting the value of a key that does not exist in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection; however, if the specified key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>, setting the <see cref="OrderedDictionary{TKey,TValue}.Item(TKey)"/> property overwrites the old value. In contrast, the <see cref="Add"/> method does not modify existing elements.</para></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
        /// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</exception>
        void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
        {
            this.Add(key, value);
        }

        /// <summary>
        /// Adds an entry with the specified key and value into the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection with the lowest available index.
        /// </summary>
        /// <param name="key">The key of the entry to add.</param>
        /// <param name="value">The value of the entry to add. This value can be <null/>.</param>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.<br/>
        /// -or-<br/>
        /// <paramref name="value"/> is <null/>, and the value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is a value type.</exception>
        /// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="key"/>.<br/>
        /// -or-<br/>
        /// The value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="value"/>.</exception>
        void IDictionary.Add(object key, object value)
        {
            this.Add(ConvertToKeyType(key), ConvertToValueType(value));
        }

        /// <summary>
        /// Determines whether the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection contains a specific key.
        /// </summary>
        /// <param name="key">The key to locate in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.</param>
        /// <returns><see langword="true"/> if the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
        /// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="key"/>.</exception>
        bool IDictionary.Contains(object key)
        {
            return this.ContainsKey(ConvertToKeyType(key));
        }

        /// <summary>
        /// Removes the entry with the specified key from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> collection.
        /// </summary>
        /// <param name="key">The key of the entry to remove.</param>
        void IDictionary.Remove(object key)
        {
            this.Remove(ConvertToKeyType(key));
        }

        /// <summary>
        /// Copies the elements of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> elements to a one-dimensional Array object at the specified index.
        /// </summary>
        /// <param name="array">The one-dimensional <see cref="Array"/> object that is the destination of the <see cref="KeyValuePair{TKey,TValue}"/> objects copied from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>. The <see cref="Array"/> must have zero-based indexing.</param>
        /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
        /// <remarks>The <see cref="ICollection.CopyTo"/> method preserves the order of the elements in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</remarks>
        void ICollection.CopyTo(Array array, int index)
        {
            ((ICollection)this.List).CopyTo(array, index);
        }

        /// <summary>
        /// Adds the specified value to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> with the specified key.
        /// </summary>
        /// <param name="item">The <see cref="KeyValuePair{TKey,TValue}"> KeyValuePair<TKey,TValue> </see> structure representing the key and value to add to the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</param>
        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
        {
            this.Add(item.Key, item.Value);
        }

        /// <summary>
        /// Determines whether the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> contains a specific key and value.
        /// </summary>
        /// <param name="item">The <see cref="KeyValuePair{TKey,TValue}"> KeyValuePair<TKey,TValue> </see> structure to locate in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</param>
        /// <returns><see langword="true"/> if <paramref name="item"/> is found in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>; otherwise, <see langword="false"/>.</returns>
        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
        {
            return ((ICollection<KeyValuePair<TKey, TValue>>)this.Dictionary).Contains(item);
        }

        /// <summary>
        /// Copies the elements of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> to an array of type <see cref="KeyValuePair{TKey,TValue}"/>, starting at the specified index.
        /// </summary>
        /// <param name="array">The one-dimensional array of type <see cref="KeyValuePair{TKey,TValue}"> KeyValuePair<TKey,TValue> </see> that is the destination of the <see cref="KeyValuePair{TKey,TValue}"> KeyValuePair<TKey,TValue> </see> elements copied from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>. The array must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            ((ICollection<KeyValuePair<TKey, TValue>>)this.Dictionary).CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// Removes a key and value from the dictionary.
        /// </summary>
        /// <param name="item">The <see cref="KeyValuePair{TKey,TValue}"> KeyValuePair<TKey,TValue> </see> structure representing the key and value to remove from the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</param>
        /// <returns><see langword="true"/> if the key and value represented by <paramref name="item"/> is successfully found and removed; otherwise, <see langword="false"/>. This method returns <see langword="false"/> if <paramref name="item"/> is not found in the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see>.</returns>
        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
        {
            return this.Remove(item.Key);
        }

        /// <summary>
        /// Converts the object passed as a key to the key type of the dictionary.
        /// </summary>
        /// <param name="keyObject">The key object to check.</param>
        /// <returns>The key object, cast as the key type of the dictionary.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="keyObject"/> is <null/>.</exception>
        /// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="keyObject"/>.</exception>
        private static TKey ConvertToKeyType(object keyObject)
        {
            if (keyObject == null)
            {
                throw new ArgumentNullException("keyObject");
            }

            if (keyObject is TKey)
            {
                return (TKey)keyObject;
            }

            throw new ArgumentException("'key' must be of type " + KeyTypeName, "keyObject");
        }

        /// <summary>
        /// Converts the object passed as a value to the value type of the dictionary.
        /// </summary>
        /// <param name="valueObject">The object to convert to the value type of the dictionary.</param>
        /// <returns>The value object, converted to the value type of the dictionary.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="valueObject"/> is <null/>, and the value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is a value type.</exception>
        /// <exception cref="ArgumentException">The value type of the <see cref="OrderedDictionary{TKey,TValue}"> OrderedDictionary<TKey,TValue> </see> is not in the inheritance hierarchy of <paramref name="valueObject"/>.</exception>
        private static TValue ConvertToValueType(object valueObject)
        {
            if (null == valueObject)
            {
                if (IsValueTypeReferenceType)
                {
                    return default(TValue);
                }

                throw new ArgumentNullException("valueObject");
            }

            if (valueObject is TValue)
            {
                return (TValue)valueObject;
            }

            throw new ArgumentException("'value' must be of type " + ValueTypeName, "valueObject");
        }

        #endregion
    }
}
分享到:
评论

相关推荐

    c# 省市区集成模块【支持延迟加载异步回调】

    void ActivationEventBeginInvoke(Func&lt;int&gt; id,Action&lt;IEnumerable&lt;T&gt;&gt; TValue = null, Action&lt;IAsyncResult&gt; Ting=null); IEnumerable&lt;T&gt; GetChildList(); void GetChildList(Action&lt;IEnumerable&lt;T&gt;&gt; TValue)...

    C#_集合类_Array,Arraylist,List,Hashtable,Dictionary,Stack,Queue_学习资料

    我们经常用HashTable 来存储将要写入到数据库或者返回的信息,在这之间要不断的进行类型的转化,增加了系统装箱和拆箱的负担,如果我们操纵的数据类型相对确定的化 用Dictionary&lt;TKey,TValue&gt; 集合类来存储数据就...

    Bee-tree.zip

    尽管不像.NET的Dictionary &lt;TKey,TValue&gt;类那样使用,但SortedDictionary &lt;TKey,TValue&gt;是BCL集合套件的重要组成部分。 但是,框架类仅根据分类和搜索的二叉树为您提供了一种红黑树算法。 有时,B树,AVL树...

    trie:Trie(又名前缀树)C#实现。 具有固定时间的字符串前缀查找

    Trie&lt;TKey&gt; StringTrieSet StringTrie&lt;TValue&gt; 讲解 Trie&lt;TValue&gt;实现IDictionary&lt;string&gt;接口。 尝试初始化: var trie = new StringTrie&lt;TValue&gt;(); 或使用接受IEqualityComparer&lt;char&gt; comparer接口的构造...

    10个C#常用的算法与数据结构例子

    算法是解决问题的一系列步骤。算法的目标是使用尽可能少的时间和资源来找到解决方案。在C#中,算法可以用控制结构...在C#中,可以使用List&lt;T&gt;.Contains()方法或Dictionary&lt;TKey, TValue&gt;.ContainsKey()方法来查找元素。

    nlight:.NET项目的工具箱

    NLight .NET项目的工具箱特征NLight.Collections BufferManager :维护一组大型数组,并为客户端提供它们可以用作缓冲区的段OrderedDictionary&lt;TKey&gt; :还通过实现IReadOnlyList&lt;TValue&gt;跟踪项目顺序的字典Trees....

    Linq基础学习资料,通俗易懂

    3.5 SortedList&lt;TKey,TValue&gt; 7 3.6 Queue&lt;T&gt; 8 3.7 Stack&lt;T&gt; 8 3.8 LinkedList&lt;T&gt; 8 3.9 HashSet&lt;T&gt; 9 4 System.Linq 10 4.1 System.Linq.Enumerable 10 4.2 System.Linq.Queryable 10 4.3 System.Linq....

    WPF 数据绑定模式

    1.使用ObservableCollection 来声明这个数据集合,不能使用ListT&lt;T&gt;或者Dictionary&lt;TKey,TValue&gt;。Observable意味着MVVM中的View可以观察你的集合对象。当我们数据集合变化时,界面会发生相应的变化。 2.实现一个...

    Unity3d可编辑字典Dictionary脚本

    - Unity的inspector不会在inspector中公开Dictionary类&lt;Tkey, Tvalue&gt; - Unity不序列化字典信息,因此按下播放或重新加载场景时,收集的所有字典数据都会丢失。 解决方案: - 为MonoBehaviour创建自定义编辑器,利用...

    WebBrowser.zip

    //var v = new Dictionary(Tkey,Tvalue); var v = new Dictionary&lt;string, object&gt;(); v["mode"] = "fixed_servers"; v["server"] = Address; string error; bool success = rc.SetPreference("proxy", v, out...

    c# in depth的泛型实现实例代码

    Dictionary&lt;TKey&gt;就是一个好的例子,它有个TryValue方法,它的作用有点儿像对数值类型进行处理的TryParse方法:他用一个输出参数来接收你打算获取的值,用一个Boolean返回值显示它是否成功。这意味着方法必须用...

    asp.net 计算字符串中各个字符串出现的次数

    第二步,用Dictionary(TKey,TValue)实例化。 代码如下: Dictionary&lt;string&gt; Statistics = new Dictionary&lt;string&gt;(); 第三步,统计: 代码如下: foreach (string w in arr) { if (Statistics.ContainsKey(w)) { ...

    浅谈二叉查找树的集合总结分析

    我们都知道Dictionary&lt;TKey&gt;查找元素非常快,其实现原理是:将你TKey的值散列到数组的指定位置,将TValue的值存入对应的位置,由于取和存用的是同一个算法,所以就很容易定位到TValue的位置,花费的时间基本上就是...

    C#创建安全的字典(Dictionary)存储结构

    在上面介绍过栈(Stack)的存储结构,接下来介绍另一种存储结构字典(Dictionary)。 字典(Dictionary)里面的每一个元素... public void Add(TKey key, TValue value) { Insert(key, value, true); } private voi

    Typescriptr:AC#到TypeScript转换器,着重于易用性和客户端方面的出色表现

    具体来说,它执行以下操作: 它将IDictionary &lt;TKey&gt;呈现为开箱即用的{ [key: TKey]: TValue } 它使IEnumerable对T[]开箱即用枚举值呈现为字符串而不是数字,并且与常规类型分开生成。 枚举属性呈现为字符串联合...

    FSharpWrap:根据 F# 项目文件的引用自动生成 F# 模块和函数的实用程序

    例子包含以下 C# 类的依赖项: public class ExampleDictionary &lt; TKey&gt;{ public void SetItem ( TKey key , TValue value );} 然后可以按以下方式使用: let myDict = new ExampleDictionary &lt; string&gt; ()...

    研华PCI-1761接点检测

    Do Until Tvalue &lt; 1 '循环直到变量Tvalue的值小于 1 才结束循环 aa = CStr(Tvalue Mod 2) & aa '变量aa 逐一累加 Tvalue = Int(Tvalue / 2) '将变量Tvalue除以2 再用函数Int将此数值去除小数 整数化 Loop Ten2Two...

    DS18B20温度计 1602液晶显示温度

    #include&lt;reg51.h&gt; #define uchar unsigned char #define uint unsigned int sbit DQ=P3^7;//ds18b20与单片机连接口 sbit RS=P3^0; sbit RW=P3^1; sbit EN=P3^2; unsigned char code str1[]={"temperature: "}; ...

Global site tag (gtag.js) - Google Analytics