cleol
authorJb Evain <jbevain@gmail.com>
Fri, 23 Apr 2010 12:57:34 +0000 (12:57 -0000)
committerJb Evain <jbevain@gmail.com>
Fri, 23 Apr 2010 12:57:34 +0000 (12:57 -0000)
svn path=/trunk/mcs/; revision=156004

mcs/class/Mono.Cecil/Mono.Cecil/NameObjectCollectionBase.cs

index 5008cbd1515a2bf851130183bb4cee06dee567d3..80b0c11d519f8033d30d522b43f96df175c559f5 100644 (file)
-using System;\r
-using System.Collections;\r
-using System.Runtime.Serialization;\r
-\r
-#if NO_SYSTEM_DLL\r
-namespace System.Collections.Specialized\r
-{\r
-       [Serializable]\r
-       public abstract class NameObjectCollectionBase : ICollection, IEnumerable, ISerializable, IDeserializationCallback\r
-       {\r
-               private Hashtable m_ItemsContainer;\r
-               /// <summary>\r
-               /// Extends Hashtable based Items container to support storing null-key pairs\r
-               /// </summary>\r
-               private _Item m_NullKeyItem;\r
-               private ArrayList m_ItemsArray;\r
-               private IHashCodeProvider m_hashprovider;\r
-               private IComparer m_comparer;\r
-               private int m_defCapacity;\r
-               private bool m_readonly;\r
-               SerializationInfo infoCopy;\r
-               private KeysCollection keyscoll;\r
-#if NET_2_0\r
-               private IEqualityComparer equality_comparer;\r
-\r
-               internal IEqualityComparer EqualityComparer {\r
-                       get { return equality_comparer; }\r
-               }\r
-#endif\r
-               internal IComparer Comparer\r
-               {\r
-                       get { return m_comparer; }\r
-               }\r
-\r
-               internal IHashCodeProvider HashCodeProvider\r
-               {\r
-                       get { return m_hashprovider; }\r
-               }\r
-\r
-               internal class _Item\r
-               {\r
-                       public string key;\r
-                       public object value;\r
-                       public _Item(string key, object value)\r
-                       {\r
-                               this.key = key;\r
-                               this.value = value;\r
-                       }\r
-               }\r
-               /// <summary>\r
-               /// Implements IEnumerable interface for KeysCollection\r
-               /// </summary>\r
-               [Serializable]\r
-               internal class _KeysEnumerator : IEnumerator\r
-               {\r
-                       private NameObjectCollectionBase m_collection;\r
-                       private int m_position;\r
-\r
-                       internal _KeysEnumerator(NameObjectCollectionBase collection)\r
-                       {\r
-                               m_collection = collection;\r
-                               Reset();\r
-                       }\r
-                       public object Current\r
-                       {\r
-\r
-                               get\r
-                               {\r
-                                       if ((m_position < m_collection.Count) || (m_position < 0))\r
-                                               return m_collection.BaseGetKey(m_position);\r
-                                       else\r
-                                               throw new InvalidOperationException();\r
-                               }\r
-\r
-                       }\r
-                       public bool MoveNext()\r
-                       {\r
-                               return ((++m_position) < m_collection.Count);\r
-                       }\r
-                       public void Reset()\r
-                       {\r
-                               m_position = -1;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK: Represents a collection of the String keys of a collection.\r
-               /// </summary>\r
-               [Serializable]\r
-               public class KeysCollection : ICollection, IEnumerable\r
-               {\r
-                       private NameObjectCollectionBase m_collection;\r
-\r
-                       internal KeysCollection(NameObjectCollectionBase collection)\r
-                       {\r
-                               this.m_collection = collection;\r
-                       }\r
-\r
-                       public virtual string Get(int index)\r
-                       {\r
-                               return m_collection.BaseGetKey(index);\r
-                       }\r
-\r
-                       // ICollection methods -----------------------------------\r
-                       void ICollection.CopyTo(Array array, int arrayIndex)\r
-                       {\r
-                               ArrayList items = m_collection.m_ItemsArray;\r
-#if NET_2_0\r
-                               if (null == array)\r
-                                       throw new ArgumentNullException ("array");\r
-\r
-                               if (arrayIndex < 0)\r
-                                       throw new ArgumentOutOfRangeException ("arrayIndex");\r
-\r
-                               if ((array.Length > 0) && (arrayIndex >= array.Length))\r
-                                       throw new ArgumentException ("arrayIndex is equal to or greater than array.Length");\r
-\r
-                               if (arrayIndex + items.Count > array.Length)\r
-                                       throw new ArgumentException ("Not enough room from arrayIndex to end of array for this KeysCollection");\r
-#endif\r
-\r
-                               if (array != null && array.Rank > 1)\r
-                                       throw new ArgumentException("array is multidimensional");\r
-\r
-                               object[] objArray = (object[])array;\r
-                               for (int i = 0; i < items.Count; i++, arrayIndex++)\r
-                                       objArray[arrayIndex] = ((_Item)items[i]).key;\r
-                       }\r
-\r
-                       bool ICollection.IsSynchronized\r
-                       {\r
-                               get\r
-                               {\r
-                                       return false;\r
-                               }\r
-                       }\r
-                       object ICollection.SyncRoot\r
-                       {\r
-                               get\r
-                               {\r
-                                       return m_collection;\r
-                               }\r
-                       }\r
-                       /// <summary>\r
-                       /// Gets the number of keys in the NameObjectCollectionBase.KeysCollection\r
-                       /// </summary>\r
-                       public int Count\r
-                       {\r
-                               get\r
-                               {\r
-                                       return m_collection.Count;\r
-                               }\r
-                       }\r
-\r
-                       public string this[int index]\r
-                       {\r
-                               get { return Get(index); }\r
-                       }\r
-\r
-                       // IEnumerable methods --------------------------------\r
-                       /// <summary>\r
-                       /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.KeysCollection.\r
-                       /// </summary>\r
-                       /// <returns></returns>\r
-                       public IEnumerator GetEnumerator()\r
-                       {\r
-                               return new _KeysEnumerator(m_collection);\r
-                       }\r
-               }\r
-\r
-               //--------------- Protected Instance Constructors --------------\r
-\r
-               /// <summary>\r
-               /// SDK: Initializes a new instance of the NameObjectCollectionBase class that is empty.\r
-               /// </summary>\r
-               protected NameObjectCollectionBase()\r
-               {\r
-                       m_readonly = false;\r
-#if NET_1_0\r
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;\r
-                       m_comparer = CaseInsensitiveComparer.Default;\r
-#else\r
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;\r
-                       m_comparer = CaseInsensitiveComparer.DefaultInvariant;\r
-#endif\r
-                       m_defCapacity = 0;\r
-                       Init();\r
-               }\r
-\r
-               protected NameObjectCollectionBase(int capacity)\r
-               {\r
-                       m_readonly = false;\r
-#if NET_1_0\r
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;\r
-                       m_comparer = CaseInsensitiveComparer.Default;\r
-#else\r
-                       m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;\r
-                       m_comparer = CaseInsensitiveComparer.DefaultInvariant;\r
-#endif\r
-                       m_defCapacity = capacity;\r
-                       Init();\r
-               }\r
-\r
-#if NET_2_0\r
-\r
-               internal NameObjectCollectionBase (IEqualityComparer equalityComparer, IComparer comparer, IHashCodeProvider hcp)\r
-               {\r
-                       equality_comparer = equalityComparer;\r
-                       m_comparer = comparer;\r
-                       m_hashprovider = hcp;\r
-                       m_readonly = false;\r
-                       m_defCapacity = 0;\r
-                       Init ();\r
-               }\r
-\r
-               protected NameObjectCollectionBase (IEqualityComparer equalityComparer) : this( (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer), null, null)\r
-               {                       \r
-               }               \r
-\r
-               [Obsolete ("Use NameObjectCollectionBase(IEqualityComparer)")]\r
-#endif\r
-               protected NameObjectCollectionBase(IHashCodeProvider hashProvider, IComparer comparer)\r
-               {\r
-                       m_comparer = comparer;\r
-                       m_hashprovider = hashProvider;\r
-                       m_readonly = false;\r
-                       m_defCapacity = 0;\r
-                       Init();\r
-               }\r
-\r
-               protected NameObjectCollectionBase(SerializationInfo info, StreamingContext context)\r
-               {\r
-                       infoCopy = info;\r
-               }\r
-\r
-#if NET_2_0\r
-               protected NameObjectCollectionBase (int capacity, IEqualityComparer equalityComparer)\r
-               {\r
-                       m_readonly = false;\r
-                       equality_comparer = (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer);\r
-                       m_defCapacity = capacity;\r
-                       Init();\r
-               }\r
-\r
-               [Obsolete ("Use NameObjectCollectionBase(int,IEqualityComparer)")]\r
-#endif\r
-               protected NameObjectCollectionBase(int capacity, IHashCodeProvider hashProvider, IComparer comparer)\r
-               {\r
-                       m_readonly = false;\r
-\r
-                       m_hashprovider = hashProvider;\r
-                       m_comparer = comparer;\r
-                       m_defCapacity = capacity;\r
-                       Init();\r
-               }\r
-\r
-               private void Init()\r
-               {\r
-#if NET_2_0\r
-                       if (equality_comparer != null)\r
-                               m_ItemsContainer = new Hashtable (m_defCapacity, equality_comparer);\r
-                       else\r
-                               m_ItemsContainer = new Hashtable (m_defCapacity, m_hashprovider, m_comparer);\r
-#else\r
-                       m_ItemsContainer = new Hashtable(m_defCapacity, m_hashprovider, m_comparer);\r
-#endif\r
-                       m_ItemsArray = new ArrayList();\r
-                       m_NullKeyItem = null;\r
-               }\r
-\r
-               //--------------- Public Instance Properties -------------------\r
-\r
-               public virtual NameObjectCollectionBase.KeysCollection Keys\r
-               {\r
-                       get\r
-                       {\r
-                               if (keyscoll == null)\r
-                                       keyscoll = new KeysCollection(this);\r
-                               return keyscoll;\r
-                       }\r
-               }\r
-\r
-               //--------------- Public Instance Methods ----------------------\r
-               // \r
-               /// <summary>\r
-               /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.\r
-               /// \r
-               /// <remark>This enumerator returns the keys of the collection as strings.</remark>\r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public\r
-#if NET_2_0            \r
-               virtual\r
-#endif\r
- IEnumerator GetEnumerator()\r
-               {\r
-                       return new _KeysEnumerator(this);\r
-               }\r
-\r
-               // ISerializable\r
-               public virtual void GetObjectData(SerializationInfo info, StreamingContext context)\r
-               {\r
-                       if (info == null)\r
-                               throw new ArgumentNullException("info");\r
-\r
-                       int count = Count;\r
-                       string[] keys = new string[count];\r
-                       object[] values = new object[count];\r
-                       int i = 0;\r
-                       foreach (_Item item in m_ItemsArray)\r
-                       {\r
-                               keys[i] = item.key;\r
-                               values[i] = item.value;\r
-                               i++;\r
-                       }\r
-\r
-#if NET_2_0\r
-                       if (equality_comparer != null) {\r
-                               info.AddValue ("KeyComparer", equality_comparer, typeof (IEqualityComparer));\r
-                               info.AddValue ("Version", 4, typeof (int));\r
-                       } else {\r
-                               info.AddValue ("HashProvider", m_hashprovider, typeof (IHashCodeProvider));\r
-                               info.AddValue ("Comparer", m_comparer, typeof (IComparer));\r
-                               info.AddValue ("Version", 2, typeof (int));\r
-                       }\r
-#else\r
-                       info.AddValue("HashProvider", m_hashprovider, typeof(IHashCodeProvider));\r
-                       info.AddValue("Comparer", m_comparer, typeof(IComparer));\r
-#endif\r
-                       info.AddValue("ReadOnly", m_readonly);\r
-                       info.AddValue("Count", count);\r
-                       info.AddValue("Keys", keys, typeof(string[]));\r
-                       info.AddValue("Values", values, typeof(object[]));\r
-               }\r
-\r
-               // ICollection\r
-               public virtual int Count\r
-               {\r
-                       get\r
-                       {\r
-                               return m_ItemsArray.Count;\r
-                       }\r
-               }\r
-\r
-               bool ICollection.IsSynchronized\r
-               {\r
-                       get { return false; }\r
-               }\r
-\r
-               object ICollection.SyncRoot\r
-               {\r
-                       get { return this; }\r
-               }\r
-\r
-               void ICollection.CopyTo(Array array, int index)\r
-               {\r
-                       ((ICollection)Keys).CopyTo(array, index);\r
-               }\r
-\r
-               // IDeserializationCallback\r
-               public virtual void OnDeserialization(object sender)\r
-               {\r
-                       SerializationInfo info = infoCopy;\r
-\r
-                       // If a subclass overrides the serialization constructor\r
-                       // and inplements its own serialization process, infoCopy will\r
-                       // be null and we can ignore this callback.\r
-                       if (info == null)\r
-                               return;\r
-\r
-                       infoCopy = null;\r
-                       m_hashprovider = (IHashCodeProvider)info.GetValue("HashProvider",\r
-                                                                               typeof(IHashCodeProvider));\r
-#if NET_2_0\r
-                       if (m_hashprovider == null) {\r
-                               equality_comparer = (IEqualityComparer) info.GetValue ("KeyComparer", typeof (IEqualityComparer));\r
-                       } else {\r
-                               m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));\r
-                               if (m_comparer == null)\r
-                                       throw new SerializationException ("The comparer is null");\r
-                       }\r
-#else\r
-                       if (m_hashprovider == null)\r
-                               throw new SerializationException("The hash provider is null");\r
-\r
-                       m_comparer = (IComparer)info.GetValue("Comparer", typeof(IComparer));\r
-                       if (m_comparer == null)\r
-                               throw new SerializationException("The comparer is null");\r
-#endif\r
-                       m_readonly = info.GetBoolean("ReadOnly");\r
-                       string[] keys = (string[])info.GetValue("Keys", typeof(string[]));\r
-                       if (keys == null)\r
-                               throw new SerializationException("keys is null");\r
-\r
-                       object[] values = (object[])info.GetValue("Values", typeof(object[]));\r
-                       if (values == null)\r
-                               throw new SerializationException("values is null");\r
-\r
-                       Init();\r
-                       int count = keys.Length;\r
-                       for (int i = 0; i < count; i++)\r
-                               BaseAdd(keys[i], values[i]);\r
-               }\r
-\r
-               //--------------- Protected Instance Properties ----------------\r
-               /// <summary>\r
-               /// SDK: Gets or sets a value indicating whether the NameObjectCollectionBase instance is read-only.\r
-               /// </summary>\r
-               protected bool IsReadOnly\r
-               {\r
-                       get\r
-                       {\r
-                               return m_readonly;\r
-                       }\r
-                       set\r
-                       {\r
-                               m_readonly = value;\r
-                       }\r
-               }\r
-\r
-               //--------------- Protected Instance Methods -------------------\r
-               /// <summary>\r
-               /// Adds an Item with the specified key and value into the <see cref="NameObjectCollectionBase"/>NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <param name="name"></param>\r
-               /// <param name="value"></param>\r
-               protected void BaseAdd(string name, object value)\r
-               {\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-\r
-                       _Item newitem = new _Item(name, value);\r
-\r
-                       if (name == null)\r
-                       {\r
-                               //todo: consider nullkey entry\r
-                               if (m_NullKeyItem == null)\r
-                                       m_NullKeyItem = newitem;\r
-                       }\r
-                       else\r
-                               if (m_ItemsContainer[name] == null)\r
-                               {\r
-                                       m_ItemsContainer.Add(name, newitem);\r
-                               }\r
-                       m_ItemsArray.Add(newitem);\r
-               }\r
-\r
-               protected void BaseClear()\r
-               {\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-                       Init();\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK: Gets the value of the entry at the specified index of the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <param name="index"></param>\r
-               /// <returns></returns>\r
-               protected object BaseGet(int index)\r
-               {\r
-                       return ((_Item)m_ItemsArray[index]).value;\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK: Gets the value of the first entry with the specified key from the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <remark>CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.</remark>\r
-               /// <param name="name"></param>\r
-               /// <returns></returns>\r
-               protected object BaseGet(string name)\r
-               {\r
-                       _Item item = FindFirstMatchedItem(name);\r
-                       /// CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.\r
-                       if (item == null)\r
-                               return null;\r
-                       else\r
-                               return item.value;\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK:Returns a String array that contains all the keys in the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <returns>A String array that contains all the keys in the NameObjectCollectionBase instance.</returns>\r
-               protected string[] BaseGetAllKeys()\r
-               {\r
-                       int cnt = m_ItemsArray.Count;\r
-                       string[] allKeys = new string[cnt];\r
-                       for (int i = 0; i < cnt; i++)\r
-                               allKeys[i] = BaseGetKey(i);//((_Item)m_ItemsArray[i]).key;\r
-\r
-                       return allKeys;\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK: Returns an Object array that contains all the values in the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <returns>An Object array that contains all the values in the NameObjectCollectionBase instance.</returns>\r
-               protected object[] BaseGetAllValues()\r
-               {\r
-                       int cnt = m_ItemsArray.Count;\r
-                       object[] allValues = new object[cnt];\r
-                       for (int i = 0; i < cnt; i++)\r
-                               allValues[i] = BaseGet(i);\r
-\r
-                       return allValues;\r
-               }\r
-\r
-               protected object[] BaseGetAllValues(Type type)\r
-               {\r
-                       if (type == null)\r
-                               throw new ArgumentNullException("'type' argument can't be null");\r
-                       int cnt = m_ItemsArray.Count;\r
-                       object[] allValues = (object[])Array.CreateInstance(type, cnt);\r
-                       for (int i = 0; i < cnt; i++)\r
-                               allValues[i] = BaseGet(i);\r
-\r
-                       return allValues;\r
-               }\r
-\r
-               protected string BaseGetKey(int index)\r
-               {\r
-                       return ((_Item)m_ItemsArray[index]).key;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Gets a value indicating whether the NameObjectCollectionBase instance contains entries whose keys are not a null reference \r
-               /// </summary>\r
-               /// <returns>true if the NameObjectCollectionBase instance contains entries whose keys are not a null reference otherwise, false.</returns>\r
-               protected bool BaseHasKeys()\r
-               {\r
-                       return (m_ItemsContainer.Count > 0);\r
-               }\r
-\r
-               protected void BaseRemove(string name)\r
-               {\r
-                       int cnt = 0;\r
-                       String key;\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-                       if (name != null)\r
-                       {\r
-                               m_ItemsContainer.Remove(name);\r
-                       }\r
-                       else\r
-                       {\r
-                               m_NullKeyItem = null;\r
-                       }\r
-\r
-                       cnt = m_ItemsArray.Count;\r
-                       for (int i = 0; i < cnt; )\r
-                       {\r
-                               key = BaseGetKey(i);\r
-                               if (Equals(key, name))\r
-                               {\r
-                                       m_ItemsArray.RemoveAt(i);\r
-                                       cnt--;\r
-                               }\r
-                               else\r
-                                       i++;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="index"></param>\r
-               /// <LAME>This function implemented the way Microsoft implemented it - \r
-               /// item is removed from hashtable and array without considering the case when there are two items with the same key but different values in array.\r
-               /// E.g. if\r
-               /// hashtable is [("Key1","value1")] and array contains [("Key1","value1")("Key1","value2")] then\r
-               /// after RemoveAt(1) the collection will be in following state:\r
-               /// hashtable:[] \r
-               /// array: [("Key1","value1")] \r
-               /// It's ok only then the key is uniquely assosiated with the value\r
-               /// To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added \r
-               /// </LAME>>\r
-               protected void BaseRemoveAt(int index)\r
-               {\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-                       string key = BaseGetKey(index);\r
-                       if (key != null)\r
-                       {\r
-                               // TODO: see LAME description above\r
-                               m_ItemsContainer.Remove(key);\r
-                       }\r
-                       else\r
-                               m_NullKeyItem = null;\r
-                       m_ItemsArray.RemoveAt(index);\r
-               }\r
-\r
-               /// <summary>\r
-               /// SDK: Sets the value of the entry at the specified index of the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <param name="index"></param>\r
-               /// <param name="value"></param>\r
-               protected void BaseSet(int index, object value)\r
-               {\r
-#if NET_2_0\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-#endif\r
-                       _Item item = (_Item)m_ItemsArray[index];\r
-                       item.value = value;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance.\r
-               /// </summary>\r
-               /// <param name="name">The String key of the entry to set. The key can be a null reference </param>\r
-               /// <param name="value">The Object that represents the new value of the entry to set. The value can be a null reference</param>\r
-               protected void BaseSet(string name, object value)\r
-               {\r
-#if NET_2_0\r
-                       if (this.IsReadOnly)\r
-                               throw new NotSupportedException("Collection is read-only");\r
-#endif\r
-                       _Item item = FindFirstMatchedItem(name);\r
-                       if (item != null)\r
-                               item.value = value;\r
-                       else\r
-                               BaseAdd(name, value);\r
-               }\r
-\r
-               private _Item FindFirstMatchedItem(string name)\r
-               {\r
-                       if (name != null)\r
-                               return (_Item)m_ItemsContainer[name];\r
-                       else\r
-                       {\r
-                               //TODO: consider null key case\r
-                               return m_NullKeyItem;\r
-                       }\r
-               }\r
-\r
-               internal bool Equals(string s1, string s2)\r
-               {\r
-#if NET_2_0\r
-                       if (m_comparer != null)\r
-                               return (m_comparer.Compare (s1, s2) == 0);\r
-                       else\r
-                               return equality_comparer.Equals (s1, s2);\r
-#else\r
-                       return (m_comparer.Compare(s1, s2) == 0);\r
-#endif\r
-               }\r
-       }\r
-}\r
-#endif\r
+using System;
+using System.Collections;
+using System.Runtime.Serialization;
+
+#if NO_SYSTEM_DLL
+namespace System.Collections.Specialized
+{
+       [Serializable]
+       public abstract class NameObjectCollectionBase : ICollection, IEnumerable, ISerializable, IDeserializationCallback
+       {
+               private Hashtable m_ItemsContainer;
+               /// <summary>
+               /// Extends Hashtable based Items container to support storing null-key pairs
+               /// </summary>
+               private _Item m_NullKeyItem;
+               private ArrayList m_ItemsArray;
+               private IHashCodeProvider m_hashprovider;
+               private IComparer m_comparer;
+               private int m_defCapacity;
+               private bool m_readonly;
+               SerializationInfo infoCopy;
+               private KeysCollection keyscoll;
+#if NET_2_0
+               private IEqualityComparer equality_comparer;
+
+               internal IEqualityComparer EqualityComparer {
+                       get { return equality_comparer; }
+               }
+#endif
+               internal IComparer Comparer
+               {
+                       get { return m_comparer; }
+               }
+
+               internal IHashCodeProvider HashCodeProvider
+               {
+                       get { return m_hashprovider; }
+               }
+
+               internal class _Item
+               {
+                       public string key;
+                       public object value;
+                       public _Item(string key, object value)
+                       {
+                               this.key = key;
+                               this.value = value;
+                       }
+               }
+               /// <summary>
+               /// Implements IEnumerable interface for KeysCollection
+               /// </summary>
+               [Serializable]
+               internal class _KeysEnumerator : IEnumerator
+               {
+                       private NameObjectCollectionBase m_collection;
+                       private int m_position;
+
+                       internal _KeysEnumerator(NameObjectCollectionBase collection)
+                       {
+                               m_collection = collection;
+                               Reset();
+                       }
+                       public object Current
+                       {
+
+                               get
+                               {
+                                       if ((m_position < m_collection.Count) || (m_position < 0))
+                                               return m_collection.BaseGetKey(m_position);
+                                       else
+                                               throw new InvalidOperationException();
+                               }
+
+                       }
+                       public bool MoveNext()
+                       {
+                               return ((++m_position) < m_collection.Count);
+                       }
+                       public void Reset()
+                       {
+                               m_position = -1;
+                       }
+               }
+
+               /// <summary>
+               /// SDK: Represents a collection of the String keys of a collection.
+               /// </summary>
+               [Serializable]
+               public class KeysCollection : ICollection, IEnumerable
+               {
+                       private NameObjectCollectionBase m_collection;
+
+                       internal KeysCollection(NameObjectCollectionBase collection)
+                       {
+                               this.m_collection = collection;
+                       }
+
+                       public virtual string Get(int index)
+                       {
+                               return m_collection.BaseGetKey(index);
+                       }
+
+                       // ICollection methods -----------------------------------
+                       void ICollection.CopyTo(Array array, int arrayIndex)
+                       {
+                               ArrayList items = m_collection.m_ItemsArray;
+#if NET_2_0
+                               if (null == array)
+                                       throw new ArgumentNullException ("array");
+
+                               if (arrayIndex < 0)
+                                       throw new ArgumentOutOfRangeException ("arrayIndex");
+
+                               if ((array.Length > 0) && (arrayIndex >= array.Length))
+                                       throw new ArgumentException ("arrayIndex is equal to or greater than array.Length");
+
+                               if (arrayIndex + items.Count > array.Length)
+                                       throw new ArgumentException ("Not enough room from arrayIndex to end of array for this KeysCollection");
+#endif
+
+                               if (array != null && array.Rank > 1)
+                                       throw new ArgumentException("array is multidimensional");
+
+                               object[] objArray = (object[])array;
+                               for (int i = 0; i < items.Count; i++, arrayIndex++)
+                                       objArray[arrayIndex] = ((_Item)items[i]).key;
+                       }
+
+                       bool ICollection.IsSynchronized
+                       {
+                               get
+                               {
+                                       return false;
+                               }
+                       }
+                       object ICollection.SyncRoot
+                       {
+                               get
+                               {
+                                       return m_collection;
+                               }
+                       }
+                       /// <summary>
+                       /// Gets the number of keys in the NameObjectCollectionBase.KeysCollection
+                       /// </summary>
+                       public int Count
+                       {
+                               get
+                               {
+                                       return m_collection.Count;
+                               }
+                       }
+
+                       public string this[int index]
+                       {
+                               get { return Get(index); }
+                       }
+
+                       // IEnumerable methods --------------------------------
+                       /// <summary>
+                       /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.KeysCollection.
+                       /// </summary>
+                       /// <returns></returns>
+                       public IEnumerator GetEnumerator()
+                       {
+                               return new _KeysEnumerator(m_collection);
+                       }
+               }
+
+               //--------------- Protected Instance Constructors --------------
+
+               /// <summary>
+               /// SDK: Initializes a new instance of the NameObjectCollectionBase class that is empty.
+               /// </summary>
+               protected NameObjectCollectionBase()
+               {
+                       m_readonly = false;
+#if NET_1_0
+                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
+                       m_comparer = CaseInsensitiveComparer.Default;
+#else
+                       m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
+                       m_comparer = CaseInsensitiveComparer.DefaultInvariant;
+#endif
+                       m_defCapacity = 0;
+                       Init();
+               }
+
+               protected NameObjectCollectionBase(int capacity)
+               {
+                       m_readonly = false;
+#if NET_1_0
+                       m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
+                       m_comparer = CaseInsensitiveComparer.Default;
+#else
+                       m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
+                       m_comparer = CaseInsensitiveComparer.DefaultInvariant;
+#endif
+                       m_defCapacity = capacity;
+                       Init();
+               }
+
+#if NET_2_0
+
+               internal NameObjectCollectionBase (IEqualityComparer equalityComparer, IComparer comparer, IHashCodeProvider hcp)
+               {
+                       equality_comparer = equalityComparer;
+                       m_comparer = comparer;
+                       m_hashprovider = hcp;
+                       m_readonly = false;
+                       m_defCapacity = 0;
+                       Init ();
+               }
+
+               protected NameObjectCollectionBase (IEqualityComparer equalityComparer) : this( (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer), null, null)
+               {
+               }
+
+               [Obsolete ("Use NameObjectCollectionBase(IEqualityComparer)")]
+#endif
+               protected NameObjectCollectionBase(IHashCodeProvider hashProvider, IComparer comparer)
+               {
+                       m_comparer = comparer;
+                       m_hashprovider = hashProvider;
+                       m_readonly = false;
+                       m_defCapacity = 0;
+                       Init();
+               }
+
+               protected NameObjectCollectionBase(SerializationInfo info, StreamingContext context)
+               {
+                       infoCopy = info;
+               }
+
+#if NET_2_0
+               protected NameObjectCollectionBase (int capacity, IEqualityComparer equalityComparer)
+               {
+                       m_readonly = false;
+                       equality_comparer = (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer);
+                       m_defCapacity = capacity;
+                       Init();
+               }
+
+               [Obsolete ("Use NameObjectCollectionBase(int,IEqualityComparer)")]
+#endif
+               protected NameObjectCollectionBase(int capacity, IHashCodeProvider hashProvider, IComparer comparer)
+               {
+                       m_readonly = false;
+
+                       m_hashprovider = hashProvider;
+                       m_comparer = comparer;
+                       m_defCapacity = capacity;
+                       Init();
+               }
+
+               private void Init()
+               {
+#if NET_2_0
+                       if (equality_comparer != null)
+                               m_ItemsContainer = new Hashtable (m_defCapacity, equality_comparer);
+                       else
+                               m_ItemsContainer = new Hashtable (m_defCapacity, m_hashprovider, m_comparer);
+#else
+                       m_ItemsContainer = new Hashtable(m_defCapacity, m_hashprovider, m_comparer);
+#endif
+                       m_ItemsArray = new ArrayList();
+                       m_NullKeyItem = null;
+               }
+
+               //--------------- Public Instance Properties -------------------
+
+               public virtual NameObjectCollectionBase.KeysCollection Keys
+               {
+                       get
+                       {
+                               if (keyscoll == null)
+                                       keyscoll = new KeysCollection(this);
+                               return keyscoll;
+                       }
+               }
+
+               //--------------- Public Instance Methods ----------------------
+               //
+               /// <summary>
+               /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.
+               ///
+               /// <remark>This enumerator returns the keys of the collection as strings.</remark>
+               /// </summary>
+               /// <returns></returns>
+               public
+#if NET_2_0
+               virtual
+#endif
+ IEnumerator GetEnumerator()
+               {
+                       return new _KeysEnumerator(this);
+               }
+
+               // ISerializable
+               public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+               {
+                       if (info == null)
+                               throw new ArgumentNullException("info");
+
+                       int count = Count;
+                       string[] keys = new string[count];
+                       object[] values = new object[count];
+                       int i = 0;
+                       foreach (_Item item in m_ItemsArray)
+                       {
+                               keys[i] = item.key;
+                               values[i] = item.value;
+                               i++;
+                       }
+
+#if NET_2_0
+                       if (equality_comparer != null) {
+                               info.AddValue ("KeyComparer", equality_comparer, typeof (IEqualityComparer));
+                               info.AddValue ("Version", 4, typeof (int));
+                       } else {
+                               info.AddValue ("HashProvider", m_hashprovider, typeof (IHashCodeProvider));
+                               info.AddValue ("Comparer", m_comparer, typeof (IComparer));
+                               info.AddValue ("Version", 2, typeof (int));
+                       }
+#else
+                       info.AddValue("HashProvider", m_hashprovider, typeof(IHashCodeProvider));
+                       info.AddValue("Comparer", m_comparer, typeof(IComparer));
+#endif
+                       info.AddValue("ReadOnly", m_readonly);
+                       info.AddValue("Count", count);
+                       info.AddValue("Keys", keys, typeof(string[]));
+                       info.AddValue("Values", values, typeof(object[]));
+               }
+
+               // ICollection
+               public virtual int Count
+               {
+                       get
+                       {
+                               return m_ItemsArray.Count;
+                       }
+               }
+
+               bool ICollection.IsSynchronized
+               {
+                       get { return false; }
+               }
+
+               object ICollection.SyncRoot
+               {
+                       get { return this; }
+               }
+
+               void ICollection.CopyTo(Array array, int index)
+               {
+                       ((ICollection)Keys).CopyTo(array, index);
+               }
+
+               // IDeserializationCallback
+               public virtual void OnDeserialization(object sender)
+               {
+                       SerializationInfo info = infoCopy;
+
+                       // If a subclass overrides the serialization constructor
+                       // and inplements its own serialization process, infoCopy will
+                       // be null and we can ignore this callback.
+                       if (info == null)
+                               return;
+
+                       infoCopy = null;
+                       m_hashprovider = (IHashCodeProvider)info.GetValue("HashProvider",
+                                                                               typeof(IHashCodeProvider));
+#if NET_2_0
+                       if (m_hashprovider == null) {
+                               equality_comparer = (IEqualityComparer) info.GetValue ("KeyComparer", typeof (IEqualityComparer));
+                       } else {
+                               m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));
+                               if (m_comparer == null)
+                                       throw new SerializationException ("The comparer is null");
+                       }
+#else
+                       if (m_hashprovider == null)
+                               throw new SerializationException("The hash provider is null");
+
+                       m_comparer = (IComparer)info.GetValue("Comparer", typeof(IComparer));
+                       if (m_comparer == null)
+                               throw new SerializationException("The comparer is null");
+#endif
+                       m_readonly = info.GetBoolean("ReadOnly");
+                       string[] keys = (string[])info.GetValue("Keys", typeof(string[]));
+                       if (keys == null)
+                               throw new SerializationException("keys is null");
+
+                       object[] values = (object[])info.GetValue("Values", typeof(object[]));
+                       if (values == null)
+                               throw new SerializationException("values is null");
+
+                       Init();
+                       int count = keys.Length;
+                       for (int i = 0; i < count; i++)
+                               BaseAdd(keys[i], values[i]);
+               }
+
+               //--------------- Protected Instance Properties ----------------
+               /// <summary>
+               /// SDK: Gets or sets a value indicating whether the NameObjectCollectionBase instance is read-only.
+               /// </summary>
+               protected bool IsReadOnly
+               {
+                       get
+                       {
+                               return m_readonly;
+                       }
+                       set
+                       {
+                               m_readonly = value;
+                       }
+               }
+
+               //--------------- Protected Instance Methods -------------------
+               /// <summary>
+               /// Adds an Item with the specified key and value into the <see cref="NameObjectCollectionBase"/>NameObjectCollectionBase instance.
+               /// </summary>
+               /// <param name="name"></param>
+               /// <param name="value"></param>
+               protected void BaseAdd(string name, object value)
+               {
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+
+                       _Item newitem = new _Item(name, value);
+
+                       if (name == null)
+                       {
+                               //todo: consider nullkey entry
+                               if (m_NullKeyItem == null)
+                                       m_NullKeyItem = newitem;
+                       }
+                       else
+                               if (m_ItemsContainer[name] == null)
+                               {
+                                       m_ItemsContainer.Add(name, newitem);
+                               }
+                       m_ItemsArray.Add(newitem);
+               }
+
+               protected void BaseClear()
+               {
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+                       Init();
+               }
+
+               /// <summary>
+               /// SDK: Gets the value of the entry at the specified index of the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <param name="index"></param>
+               /// <returns></returns>
+               protected object BaseGet(int index)
+               {
+                       return ((_Item)m_ItemsArray[index]).value;
+               }
+
+               /// <summary>
+               /// SDK: Gets the value of the first entry with the specified key from the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <remark>CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.</remark>
+               /// <param name="name"></param>
+               /// <returns></returns>
+               protected object BaseGet(string name)
+               {
+                       _Item item = FindFirstMatchedItem(name);
+                       /// CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.
+                       if (item == null)
+                               return null;
+                       else
+                               return item.value;
+               }
+
+               /// <summary>
+               /// SDK:Returns a String array that contains all the keys in the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <returns>A String array that contains all the keys in the NameObjectCollectionBase instance.</returns>
+               protected string[] BaseGetAllKeys()
+               {
+                       int cnt = m_ItemsArray.Count;
+                       string[] allKeys = new string[cnt];
+                       for (int i = 0; i < cnt; i++)
+                               allKeys[i] = BaseGetKey(i);//((_Item)m_ItemsArray[i]).key;
+
+                       return allKeys;
+               }
+
+               /// <summary>
+               /// SDK: Returns an Object array that contains all the values in the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <returns>An Object array that contains all the values in the NameObjectCollectionBase instance.</returns>
+               protected object[] BaseGetAllValues()
+               {
+                       int cnt = m_ItemsArray.Count;
+                       object[] allValues = new object[cnt];
+                       for (int i = 0; i < cnt; i++)
+                               allValues[i] = BaseGet(i);
+
+                       return allValues;
+               }
+
+               protected object[] BaseGetAllValues(Type type)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException("'type' argument can't be null");
+                       int cnt = m_ItemsArray.Count;
+                       object[] allValues = (object[])Array.CreateInstance(type, cnt);
+                       for (int i = 0; i < cnt; i++)
+                               allValues[i] = BaseGet(i);
+
+                       return allValues;
+               }
+
+               protected string BaseGetKey(int index)
+               {
+                       return ((_Item)m_ItemsArray[index]).key;
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether the NameObjectCollectionBase instance contains entries whose keys are not a null reference
+               /// </summary>
+               /// <returns>true if the NameObjectCollectionBase instance contains entries whose keys are not a null reference otherwise, false.</returns>
+               protected bool BaseHasKeys()
+               {
+                       return (m_ItemsContainer.Count > 0);
+               }
+
+               protected void BaseRemove(string name)
+               {
+                       int cnt = 0;
+                       String key;
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+                       if (name != null)
+                       {
+                               m_ItemsContainer.Remove(name);
+                       }
+                       else
+                       {
+                               m_NullKeyItem = null;
+                       }
+
+                       cnt = m_ItemsArray.Count;
+                       for (int i = 0; i < cnt; )
+                       {
+                               key = BaseGetKey(i);
+                               if (Equals(key, name))
+                               {
+                                       m_ItemsArray.RemoveAt(i);
+                                       cnt--;
+                               }
+                               else
+                                       i++;
+                       }
+               }
+
+               /// <summary>
+               ///
+               /// </summary>
+               /// <param name="index"></param>
+               /// <LAME>This function implemented the way Microsoft implemented it -
+               /// item is removed from hashtable and array without considering the case when there are two items with the same key but different values in array.
+               /// E.g. if
+               /// hashtable is [("Key1","value1")] and array contains [("Key1","value1")("Key1","value2")] then
+               /// after RemoveAt(1) the collection will be in following state:
+               /// hashtable:[]
+               /// array: [("Key1","value1")]
+               /// It's ok only then the key is uniquely assosiated with the value
+               /// To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added
+               /// </LAME>>
+               protected void BaseRemoveAt(int index)
+               {
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+                       string key = BaseGetKey(index);
+                       if (key != null)
+                       {
+                               // TODO: see LAME description above
+                               m_ItemsContainer.Remove(key);
+                       }
+                       else
+                               m_NullKeyItem = null;
+                       m_ItemsArray.RemoveAt(index);
+               }
+
+               /// <summary>
+               /// SDK: Sets the value of the entry at the specified index of the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <param name="index"></param>
+               /// <param name="value"></param>
+               protected void BaseSet(int index, object value)
+               {
+#if NET_2_0
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+#endif
+                       _Item item = (_Item)m_ItemsArray[index];
+                       item.value = value;
+               }
+
+               /// <summary>
+               /// Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance.
+               /// </summary>
+               /// <param name="name">The String key of the entry to set. The key can be a null reference </param>
+               /// <param name="value">The Object that represents the new value of the entry to set. The value can be a null reference</param>
+               protected void BaseSet(string name, object value)
+               {
+#if NET_2_0
+                       if (this.IsReadOnly)
+                               throw new NotSupportedException("Collection is read-only");
+#endif
+                       _Item item = FindFirstMatchedItem(name);
+                       if (item != null)
+                               item.value = value;
+                       else
+                               BaseAdd(name, value);
+               }
+
+               private _Item FindFirstMatchedItem(string name)
+               {
+                       if (name != null)
+                               return (_Item)m_ItemsContainer[name];
+                       else
+                       {
+                               //TODO: consider null key case
+                               return m_NullKeyItem;
+                       }
+               }
+
+               internal bool Equals(string s1, string s2)
+               {
+#if NET_2_0
+                       if (m_comparer != null)
+                               return (m_comparer.Compare (s1, s2) == 0);
+                       else
+                               return equality_comparer.Equals (s1, s2);
+#else
+                       return (m_comparer.Compare(s1, s2) == 0);
+#endif
+               }
+       }
+}
+#endif