* InstanceDescriptor.cs: Allow null members. Fixed exception messages.
[mono.git] / mcs / class / System / System.Collections.Specialized / HybridDictionary.cs
index 988a6c65795be31eafc1f49e4ace1d1b376f995b..58fc1ca236f5813307b94e2ecab962b0e8b9135e 100644 (file)
-//\r
-// System.Collections.Specialized.HybridDictionary.cs\r
-//\r
-// Author:\r
+//
+// System.Collections.Specialized.HybridDictionary.cs
+//
+// Author:
 //   Lawrence Pit (loz@cable.a2000.nl)
+//   Raja R Harinath <rharinath@novell.com>
+//
+// Copyright (C) 2004, 2005 Novell (http://www.novell.com)
+//
+
 //
-// Copyright (C) 2004 Novell (http://www.novell.com)\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-\r
-namespace System.Collections.Specialized {\r
-       \r
-       [Serializable]\r
-       public class HybridDictionary : IDictionary, ICollection, IEnumerable {\r
-               \r
-               private const int switchAfter = 10;\r
-\r
-               private ListDictionary list;\r
-               private Hashtable hashtable;\r
-               private bool caseInsensitive = false;\r
-\r
-               // Constructors\r
-               \r
-               public HybridDictionary() : this (0, false) { }\r
-               \r
-               public HybridDictionary (bool caseInsensitive) : this (0, caseInsensitive) { }\r
-               \r
-               public HybridDictionary (int initialSize) : this (initialSize, false) { }\r
-               \r
-               public HybridDictionary(int initialSize, bool caseInsensitive) \r
-               {\r
-                       this.caseInsensitive = caseInsensitive;\r
-               \r
-                       if (initialSize <= switchAfter)\r
-                               if (caseInsensitive)\r
-                                       list = new ListDictionary (CaseInsensitiveComparer.Default);\r
-                               else\r
-                                       list = new ListDictionary ();\r
-                       else\r
-                               if (caseInsensitive) \r
-                                       hashtable = new Hashtable (initialSize, \r
-                                                       CaseInsensitiveHashCodeProvider.Default, \r
-                                                       CaseInsensitiveComparer.Default);\r
-                               else\r
-                                       hashtable = new Hashtable (initialSize);\r
-               }               \r
-\r
-               \r
-               // Properties\r
-               \r
-               public int Count {\r
-                       get {\r
-                               if (list != null)\r
-                                       return list.Count;\r
-                               return hashtable.Count;\r
-                       }\r
-               }\r
-               \r
-               public bool IsFixedSize {\r
-                       get { return false; }\r
-               }\r
-               \r
-               public bool IsReadOnly {\r
-                       get { return false; }\r
-               }\r
-               \r
-               public bool IsSynchronized {\r
-                       get { return false; }\r
-               }\r
-               \r
-               public object this [object key] {\r
-                       get { \r
-                               if (key == null)\r
-                                       throw new ArgumentNullException("key");\r
-                               if (list != null)\r
-                                       return list [key];\r
-                               return hashtable [key];\r
-                       }\r
-                       set { \r
-                               if (list != null)\r
-                                       if (list.Count >= switchAfter) \r
-                                               Switch ();\r
-                                       else {\r
-                                               list [key] = value;\r
-                                               return;\r
-                                       }\r
-                               hashtable [key] = value;\r
-                       }\r
-               }\r
-               \r
-               public ICollection Keys {\r
-                       get {\r
-                               if (list != null)\r
-                                       return list.Keys;\r
-                               return hashtable.Keys;\r
-                       }\r
-               }\r
-               \r
-               public object SyncRoot {\r
-                       get { return this; }\r
-               }\r
-               \r
-               public ICollection Values {\r
-                       get { \r
-                               if (list != null)\r
-                                       return list.Values;\r
-                               return hashtable.Values;\r
-                       }\r
-               }\r
-               \r
-               \r
-               // Methods\r
-               \r
-               public void Add (object key, object value) \r
-               {\r
-                       if (list != null)\r
-                               if (list.Count >= switchAfter) \r
-                                       Switch ();\r
-                               else {\r
-                                       list.Add (key, value);\r
-                                       return;\r
-                               }\r
-                       hashtable.Add (key, value);\r
-               }\r
-               \r
-               public void Clear ()\r
-               {\r
-                       if (caseInsensitive)\r
-                               list = new ListDictionary (CaseInsensitiveComparer.Default);\r
-                       else\r
-                               list = new ListDictionary ();\r
-                       hashtable = null;\r
-               }\r
-               \r
-               public bool Contains (object key)\r
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Collections.Specialized {
+
+       [Serializable]
+       public class HybridDictionary : IDictionary, ICollection, IEnumerable {
+
+               private const int switchAfter = 10;
+
+               private IDictionary inner {
+                       get { return list == null ? (IDictionary) hashtable : (IDictionary) list; }
+               }
+
+               private bool caseInsensitive;
+               private Hashtable hashtable;
+               private ListDictionary list;
+
+               // Constructors
+
+               public HybridDictionary() : this (0, false) { }
+
+               public HybridDictionary (bool caseInsensitive) : this (0, caseInsensitive) { }
+
+               public HybridDictionary (int initialSize) : this (initialSize, false) { }
+
+               public HybridDictionary (int initialSize, bool caseInsensitive)
                {
-                       if (key == null) {
-                               if (this.Count == 0)
-                                       return false;
-                               else
-                                       throw new ArgumentNullException ("key");\r
+                       this.caseInsensitive = caseInsensitive;
+
+                       IComparer comparer = caseInsensitive ? CaseInsensitiveComparer.DefaultInvariant : null;
+                       IHashCodeProvider hcp = caseInsensitive ? CaseInsensitiveHashCodeProvider.DefaultInvariant : null;
+
+                       if (initialSize <= switchAfter)
+                               list = new ListDictionary (comparer);
+                       else
+                               hashtable = new Hashtable (initialSize, hcp, comparer);
+               }
+
+               // Properties
+
+               public int Count {
+                       get { return inner.Count; }
+               }
+
+               public bool IsFixedSize {
+                       get { return false; }
+               }
+
+               public bool IsReadOnly {
+                       get { return false; }
+               }
+
+               public bool IsSynchronized {
+                       get { return false; }
+               }
+
+               public object this [object key] {
+                       get { return inner [key]; }
+
+                       set {
+                               inner [key] = value;
+                               if (list != null && Count > switchAfter)
+                                       Switch ();
                        }
-                       if (list != null)\r
-                               return list.Contains (key);\r
-                       return hashtable.Contains (key);\r
-               }\r
-               \r
-               public void CopyTo (Array array, int index)\r
-               {\r
-                       if (list != null) \r
-                               list.CopyTo (array, index);\r
-                       else\r
-                               hashtable.CopyTo (array, index);\r
-               }\r
-               \r
-               public IDictionaryEnumerator GetEnumerator ()\r
-               {\r
-                       if (list != null)\r
-                               return list.GetEnumerator ();\r
-                       return hashtable.GetEnumerator ();\r
-               }\r
-\r
-               IEnumerator IEnumerable.GetEnumerator ()\r
-               {\r
-                       return GetEnumerator ();\r
-               }\r
-\r
-               public void Remove (object key)\r
-               {\r
-                       if (list != null)\r
-                               list.Remove (key);\r
-                       else    \r
-                               hashtable.Remove (key);\r
-               }\r
-               \r
-               private void Switch ()\r
-               {\r
-                       if (caseInsensitive) \r
-                               hashtable = new Hashtable (switchAfter + 1,\r
-                                                       CaseInsensitiveHashCodeProvider.Default, \r
-                                                       CaseInsensitiveComparer.Default);\r
-                       else\r
-                               hashtable = new Hashtable (switchAfter + 1);\r
-                       IDictionaryEnumerator e = list.GetEnumerator ();\r
-                       while (e.MoveNext ())\r
-                               hashtable.Add (e.Key, e.Value);\r
-                       list = null;\r
-               }\r
-       }\r
-}\r
+               }
+
+               public ICollection Keys {
+                       get { return inner.Keys; }
+               }
+
+               public object SyncRoot {
+                       get { return this; }
+               }
+
+               public ICollection Values {
+                       get { return inner.Values; }
+               }
+
+
+               // Methods
+
+               public void Add (object key, object value)
+               {
+                       inner.Add (key, value);
+                       if (list != null && Count > switchAfter)
+                               Switch ();
+               }
+
+               public void Clear ()
+               {
+                       // According to MSDN, this doesn't switch a Hashtable back to a ListDictionary
+                       inner.Clear ();
+               }
+
+               public bool Contains (object key)
+               {
+#if NET_2_0
+                       return inner.Contains (key);
+#else
+                       // if the dictionary is empty, 'Contains (null)' doesn't throw an ArgumentNullException
+                       return Count != 0 && inner.Contains (key);
+#endif
+               }
+
+               public void CopyTo (Array array, int index)
+               {
+                       inner.CopyTo (array, index);
+               }
+
+               public IDictionaryEnumerator GetEnumerator ()
+               {
+                       return inner.GetEnumerator ();
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+
+               public void Remove (object key)
+               {
+                       // According to MSDN, this does not switch a Hashtable back to a ListDictionary
+                       // even if Count falls below switchAfter
+                       inner.Remove (key);
+               }
+
+               private void Switch ()
+               {
+                       IComparer comparer = caseInsensitive ? CaseInsensitiveComparer.DefaultInvariant : null;
+                       IHashCodeProvider hcp = caseInsensitive ? CaseInsensitiveHashCodeProvider.DefaultInvariant : null;
+
+                       hashtable = new Hashtable (list, hcp, comparer);
+                       list.Clear ();
+                       list = null;
+               }
+       }
+}