Generics C#

//http://visualizer.codeplex.com/license
//Microsoft Public License (Ms-PL)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Redwerb.BizArk.Core.Collections
{
    /// 
    /// Represents a generic collection of key/value pairs. The enumerator returns the values in the order assigned.
    /// 

    /// 
    /// 
    public class HashList
        : IList
    {
        #region Fields and Properties
        private Dictionary mDictionary = new Dictionary();
        private List mList = new List();
        /// 
        /// Gets or sets the value for the given key.
        /// 

        /// 
        /// 
        public TValue this[TKey key]
        {
            get { return GetValue(key); }
            set
            {
                if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
                SetValue(key, value);
            }
        }
        /// 
        /// Gets or sets the value at the designated index.
        /// 

        /// 
        /// 
        public TValue this[int index]
        {
            get { return mList[index]; }
            set
            {
                if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
                mList[index] = value;
            }
        }
        /// 
        /// Gets the number of items in the list.
        /// 

        public int Count
        {
            get { return mList.Count; }
        }
        private bool mIsReadOnly = false;
        /// 
        /// Gets a value that determines if the list if readonly.
        /// 

        public bool IsReadOnly
        {
            get { return mIsReadOnly; }
            protected set { mIsReadOnly = value; }
        }
        #endregion
        #region Methods
        /// 
        /// Adds the value to the list.
        /// 

        /// 
        /// 
        /// 
        public void Insert(int index, TKey key, TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (mDictionary.ContainsKey(key)) throw new ArgumentException("Key already exists in the collection.");
            mList.Insert(index, value);
            foreach (var item in mDictionary.ToArray())
            {
                if (item.Value >= index)
                    mDictionary[item.Key] = item.Value + 1;
            }
            mDictionary.Add(key, index);
        }
        /// 
        /// Adds the value to the list.
        /// 

        /// 
        /// 
        public void Add(TKey key, TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (mDictionary.ContainsKey(key)) throw new ArgumentException("Key already exists in the collection.");
            SetValue(key, value);
        }
        /// 
        /// Removes the item from the list.
        /// 

        /// 
        /// 
        public bool Remove(TKey key)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            if (!mDictionary.ContainsKey(key)) return false;
            var i = mDictionary[key];
            mDictionary.Remove(key);
            mList.RemoveAt(i);
            foreach (var item in mDictionary.ToArray())
            {
                if (item.Value > i)
                    mDictionary[item.Key] = item.Value - 1;
            }
            return true;
        }
        /// 
        /// Removes the item from the list.
        /// 

        /// 
        /// 
        public bool Remove(TValue value)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            var key = GetKey(value);
            return Remove(key);
        }
        /// 
        /// Removes the value at the designated index.
        /// 

        /// 
        public void RemoveAt(int index)
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            var key = GetKeyFromIndex(index);
            Remove(key);
        }
        /// 
        /// Removes all the items from the list.
        /// 

        public void Clear()
        {
            if (mIsReadOnly) throw new InvalidOperationException("The list is readonly.");
            mDictionary.Clear();
            mList.Clear();
        }
        /// 
        /// Gets the value from the list.
        /// 

        /// 
        /// 
        protected TValue GetValue(TKey key)
        {
            var i = mDictionary[key];
            return mList[i];
        }
        /// 
        /// Gets the value from the list. If the key is not in the list, returns the default value.
        /// 

        /// 
        /// Default value to return if the key does not exist.
        /// 
        public TValue GetValue(TKey key, TValue dflt)
        {
            TValue value;
            if (TryGetValue(key, out value)) return value;
            return dflt;
        }
        /// 
        /// Gets the value from the list. Returns true if the value exists, otherwise false.
        /// 

        /// 
        /// 
        /// 
        public bool TryGetValue(TKey key, out TValue value)
        {
            if (!mDictionary.ContainsKey(key))
            {
                value = default(TValue);
                return false;
            }
            var i = mDictionary[key];
            value = mList[i];
            return true;
        }
        /// 
        /// Sets the value in the list.
        /// 

        /// 
        /// 
        /// 
        protected int SetValue(TKey key, TValue value)
        {
            int i;
            if (mDictionary.ContainsKey(key))
            {
                i = mDictionary[key];
                mList[i] = value;
            }
            else
            {
                mList.Add(value);
                i = mList.Count - 1;
                mDictionary.Add(key, i);
            }
            return i;
        }
        /// 
        /// Determines if the key is in the list.
        /// 

        /// 
        /// 
        public bool ContainsKey(TKey key)
        {
            return mDictionary.ContainsKey(key);
        }
        /// 
        /// Determines if the item is in the list.
        /// 

        /// 
        /// 
        public bool Contains(TValue item)
        {
            return mList.Contains(item);
        }
        /// 
        /// Gets the index of the given item.
        /// 

        /// 
        /// 
        public int IndexOf(TKey key)
        {
            if (!mDictionary.ContainsKey(key)) return -1;
            return mDictionary[key];
        }
        /// 
        /// Gets the index of the given item.
        /// 

        /// 
        /// 
        public int IndexOf(TValue value)
        {
            return mList.IndexOf(value);
        }
        /// 
        /// Gets the key based on the value.
        /// 

        /// 
        /// 
        public TKey GetKey(TValue value)
        {
            var i = mList.IndexOf(value);
            if (i < 0) throw new ArgumentException("Value not found in the collection.");
            foreach (var keyVal in mDictionary)
            {
                if (keyVal.Value == i)
                    return keyVal.Key;
            }
            // This should never happen, but just in case.
            throw new InvalidOperationException("The key was not found in the collection.");
        }
        /// 
        /// Gets the key based on the index.
        /// 

        /// 
        /// 
        public TKey GetKeyFromIndex(int index)
        {
            foreach (var item in mDictionary)
                if (item.Value == index) return item.Key;
            throw new ArgumentOutOfRangeException("The index was not found in the dictionary.");
        }
        /// 
        /// Returns the collection of keys.
        /// 

        public ICollection Keys
        {
            get { return mDictionary.Keys; }
        }
        /// 
        /// Gets the enumerator for the list.
        /// 

        /// 
        public IEnumerator GetEnumerator()
        {
            return mList.GetEnumerator();
        }
        /// 
        /// Gets the enumerator for the list.
        /// 

        /// 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        /// 
        /// Gets an array of the values.
        /// 

        /// 
        public TValue[] ToArray()
        {
            return mList.ToArray();
        }
        /// 
        /// Copies the values to an array.
        /// 

        /// 
        /// 
        void ICollection.CopyTo(TValue[] array, int arrayIndex)
        {
            mList.CopyTo(array, arrayIndex);
        }
        #endregion
        #region Unsupported IList methods
        void IList.Insert(int index, TValue item)
        {
            throw new NotSupportedException("Cannot insert values without the key.");
        }
        void ICollection.Add(TValue item)
        {
            throw new NotSupportedException("Cannot add values without the key.");
        }
        #endregion
    }
}