mscorlib(4.0.0.0) API with additions
Hashtable.cs
2 using System.Diagnostics;
6 using System.Security;
8 using System.Threading;
9 
10 namespace System.Collections
11 {
13  [Serializable]
14  [DebuggerTypeProxy(typeof(HashtableDebugView))]
15  [DebuggerDisplay("Count = {Count}")]
16  [ComVisible(true)]
18  {
19  private struct bucket
20  {
21  public object key;
22 
23  public object val;
24 
25  public int hash_coll;
26  }
27 
28  [Serializable]
29  private class KeyCollection : ICollection, IEnumerable
30  {
31  private Hashtable _hashtable;
32 
33  public virtual bool IsSynchronized => _hashtable.IsSynchronized;
34 
35  public virtual object SyncRoot => _hashtable.SyncRoot;
36 
37  public virtual int Count => _hashtable.count;
38 
39  internal KeyCollection(Hashtable hashtable)
40  {
41  _hashtable = hashtable;
42  }
43 
44  public virtual void CopyTo(Array array, int arrayIndex)
45  {
46  if (array == null)
47  {
48  throw new ArgumentNullException("array");
49  }
50  if (array.Rank != 1)
51  {
52  throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
53  }
54  if (arrayIndex < 0)
55  {
56  throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
57  }
58  if (array.Length - arrayIndex < _hashtable.count)
59  {
60  throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
61  }
62  _hashtable.CopyKeys(array, arrayIndex);
63  }
64 
65  public virtual IEnumerator GetEnumerator()
66  {
67  return new HashtableEnumerator(_hashtable, 1);
68  }
69  }
70 
71  [Serializable]
72  private class ValueCollection : ICollection, IEnumerable
73  {
74  private Hashtable _hashtable;
75 
76  public virtual bool IsSynchronized => _hashtable.IsSynchronized;
77 
78  public virtual object SyncRoot => _hashtable.SyncRoot;
79 
80  public virtual int Count => _hashtable.count;
81 
82  internal ValueCollection(Hashtable hashtable)
83  {
84  _hashtable = hashtable;
85  }
86 
87  public virtual void CopyTo(Array array, int arrayIndex)
88  {
89  if (array == null)
90  {
91  throw new ArgumentNullException("array");
92  }
93  if (array.Rank != 1)
94  {
95  throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
96  }
97  if (arrayIndex < 0)
98  {
99  throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
100  }
101  if (array.Length - arrayIndex < _hashtable.count)
102  {
103  throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
104  }
105  _hashtable.CopyValues(array, arrayIndex);
106  }
107 
108  public virtual IEnumerator GetEnumerator()
109  {
110  return new HashtableEnumerator(_hashtable, 2);
111  }
112  }
113 
114  [Serializable]
115  private class SyncHashtable : Hashtable, IEnumerable
116  {
117  protected Hashtable _table;
118 
119  public override int Count => _table.Count;
120 
121  public override bool IsReadOnly => _table.IsReadOnly;
122 
123  public override bool IsFixedSize => _table.IsFixedSize;
124 
125  public override bool IsSynchronized => true;
126 
127  public override object this[object key]
128  {
129  get
130  {
131  return _table[key];
132  }
133  set
134  {
135  lock (_table.SyncRoot)
136  {
137  _table[key] = value;
138  }
139  }
140  }
141 
142  public override object SyncRoot => _table.SyncRoot;
143 
144  public override ICollection Keys
145  {
146  get
147  {
148  lock (_table.SyncRoot)
149  {
150  return _table.Keys;
151  }
152  }
153  }
154 
155  public override ICollection Values
156  {
157  get
158  {
159  lock (_table.SyncRoot)
160  {
161  return _table.Values;
162  }
163  }
164  }
165 
166  internal SyncHashtable(Hashtable table)
167  : base(trash: false)
168  {
169  _table = table;
170  }
171 
172  internal SyncHashtable(SerializationInfo info, StreamingContext context)
173  : base(info, context)
174  {
175  _table = (Hashtable)info.GetValue("ParentTable", typeof(Hashtable));
176  if (_table == null)
177  {
178  throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
179  }
180  }
181 
182  [SecurityCritical]
183  public override void GetObjectData(SerializationInfo info, StreamingContext context)
184  {
185  if (info == null)
186  {
187  throw new ArgumentNullException("info");
188  }
189  lock (_table.SyncRoot)
190  {
191  info.AddValue("ParentTable", _table, typeof(Hashtable));
192  }
193  }
194 
195  public override void Add(object key, object value)
196  {
197  lock (_table.SyncRoot)
198  {
199  _table.Add(key, value);
200  }
201  }
202 
203  public override void Clear()
204  {
205  lock (_table.SyncRoot)
206  {
207  _table.Clear();
208  }
209  }
210 
211  public override bool Contains(object key)
212  {
213  return _table.Contains(key);
214  }
215 
216  public override bool ContainsKey(object key)
217  {
218  if (key == null)
219  {
220  throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
221  }
222  return _table.ContainsKey(key);
223  }
224 
225  public override bool ContainsValue(object key)
226  {
227  lock (_table.SyncRoot)
228  {
229  return _table.ContainsValue(key);
230  }
231  }
232 
233  public override void CopyTo(Array array, int arrayIndex)
234  {
235  lock (_table.SyncRoot)
236  {
237  _table.CopyTo(array, arrayIndex);
238  }
239  }
240 
241  public override object Clone()
242  {
243  lock (_table.SyncRoot)
244  {
245  return Synchronized((Hashtable)_table.Clone());
246  }
247  }
248 
250  {
251  return _table.GetEnumerator();
252  }
253 
254  public override IDictionaryEnumerator GetEnumerator()
255  {
256  return _table.GetEnumerator();
257  }
258 
259  public override void Remove(object key)
260  {
261  lock (_table.SyncRoot)
262  {
263  _table.Remove(key);
264  }
265  }
266 
267  public override void OnDeserialization(object sender)
268  {
269  }
270 
271  internal override KeyValuePairs[] ToKeyValuePairsArray()
272  {
273  return _table.ToKeyValuePairsArray();
274  }
275  }
276 
277  [Serializable]
278  private class HashtableEnumerator : IDictionaryEnumerator, IEnumerator, ICloneable
279  {
280  private Hashtable hashtable;
281 
282  private int bucket;
283 
284  private int version;
285 
286  private bool current;
287 
288  private int getObjectRetType;
289 
290  private object currentKey;
291 
292  private object currentValue;
293 
294  internal const int Keys = 1;
295 
296  internal const int Values = 2;
297 
298  internal const int DictEntry = 3;
299 
300  public virtual object Key
301  {
302  get
303  {
304  if (!current)
305  {
306  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
307  }
308  return currentKey;
309  }
310  }
311 
312  public virtual DictionaryEntry Entry
313  {
314  get
315  {
316  if (!current)
317  {
318  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
319  }
320  return new DictionaryEntry(currentKey, currentValue);
321  }
322  }
323 
324  public virtual object Current
325  {
326  get
327  {
328  if (!current)
329  {
330  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
331  }
332  if (getObjectRetType == 1)
333  {
334  return currentKey;
335  }
336  if (getObjectRetType == 2)
337  {
338  return currentValue;
339  }
340  return new DictionaryEntry(currentKey, currentValue);
341  }
342  }
343 
344  public virtual object Value
345  {
346  get
347  {
348  if (!current)
349  {
350  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
351  }
352  return currentValue;
353  }
354  }
355 
356  internal HashtableEnumerator(Hashtable hashtable, int getObjRetType)
357  {
358  this.hashtable = hashtable;
359  bucket = hashtable.buckets.Length;
360  version = hashtable.version;
361  current = false;
362  getObjectRetType = getObjRetType;
363  }
364 
365  public object Clone()
366  {
367  return MemberwiseClone();
368  }
369 
370  public virtual bool MoveNext()
371  {
372  if (version != hashtable.version)
373  {
374  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
375  }
376  while (bucket > 0)
377  {
378  bucket--;
379  object key = hashtable.buckets[bucket].key;
380  if (key != null && key != hashtable.buckets)
381  {
382  currentKey = key;
383  currentValue = hashtable.buckets[bucket].val;
384  current = true;
385  return true;
386  }
387  }
388  current = false;
389  return false;
390  }
391 
392  public virtual void Reset()
393  {
394  if (version != hashtable.version)
395  {
396  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
397  }
398  current = false;
399  bucket = hashtable.buckets.Length;
400  currentKey = null;
401  currentValue = null;
402  }
403  }
404 
405  internal class HashtableDebugView
406  {
407  private Hashtable hashtable;
408 
409  [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
410  public KeyValuePairs[] Items
411  {
412  get
413  {
414  return hashtable.ToKeyValuePairsArray();
415  }
416  }
417 
418  public HashtableDebugView(Hashtable hashtable)
419  {
420  if (hashtable == null)
421  {
422  throw new ArgumentNullException("hashtable");
423  }
424  this.hashtable = hashtable;
425  }
426  }
427 
428  internal const int HashPrime = 101;
429 
430  private const int InitialSize = 3;
431 
432  private const string LoadFactorName = "LoadFactor";
433 
434  private const string VersionName = "Version";
435 
436  private const string ComparerName = "Comparer";
437 
438  private const string HashCodeProviderName = "HashCodeProvider";
439 
440  private const string HashSizeName = "HashSize";
441 
442  private const string KeysName = "Keys";
443 
444  private const string ValuesName = "Values";
445 
446  private const string KeyComparerName = "KeyComparer";
447 
448  private bucket[] buckets;
449 
450  private int count;
451 
452  private int occupancy;
453 
454  private int loadsize;
455 
456  private float loadFactor;
457 
458  private volatile int version;
459 
460  private volatile bool isWriterInProgress;
461 
462  private ICollection keys;
463 
464  private ICollection values;
465 
466  private IEqualityComparer _keycomparer;
467 
468  private object _syncRoot;
469 
473  [Obsolete("Please use EqualityComparer property.")]
474  protected IHashCodeProvider hcp
475  {
476  get
477  {
478  if (_keycomparer is CompatibleComparer)
479  {
480  return ((CompatibleComparer)_keycomparer).HashCodeProvider;
481  }
482  if (_keycomparer == null)
483  {
484  return null;
485  }
486  throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
487  }
488  set
489  {
490  if (_keycomparer is CompatibleComparer)
491  {
492  CompatibleComparer compatibleComparer = (CompatibleComparer)_keycomparer;
493  _keycomparer = new CompatibleComparer(compatibleComparer.Comparer, value);
494  return;
495  }
496  if (_keycomparer == null)
497  {
498  _keycomparer = new CompatibleComparer(null, value);
499  return;
500  }
501  throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
502  }
503  }
504 
508  [Obsolete("Please use KeyComparer properties.")]
509  protected IComparer comparer
510  {
511  get
512  {
513  if (_keycomparer is CompatibleComparer)
514  {
515  return ((CompatibleComparer)_keycomparer).Comparer;
516  }
517  if (_keycomparer == null)
518  {
519  return null;
520  }
521  throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
522  }
523  set
524  {
525  if (_keycomparer is CompatibleComparer)
526  {
527  CompatibleComparer compatibleComparer = (CompatibleComparer)_keycomparer;
528  _keycomparer = new CompatibleComparer(value, compatibleComparer.HashCodeProvider);
529  return;
530  }
531  if (_keycomparer == null)
532  {
533  _keycomparer = new CompatibleComparer(value, null);
534  return;
535  }
536  throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
537  }
538  }
539 
543  protected IEqualityComparer EqualityComparer => _keycomparer;
544 
551  public virtual object this[object key]
552  {
553  get
554  {
555  if (key == null)
556  {
557  throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
558  }
559  bucket[] array = buckets;
560  uint seed;
561  uint incr;
562  uint num = InitHash(key, array.Length, out seed, out incr);
563  int num2 = 0;
564  int num3 = (int)(seed % (uint)array.Length);
565  bucket bucket;
566  do
567  {
568  int num4 = 0;
569  int num5;
570  do
571  {
572  num5 = version;
573  bucket = array[num3];
574  if (++num4 % 8 == 0)
575  {
576  Thread.Sleep(1);
577  }
578  }
579  while (isWriterInProgress || num5 != version);
580  if (bucket.key == null)
581  {
582  return null;
583  }
584  if ((bucket.hash_coll & int.MaxValue) == num && KeyEquals(bucket.key, key))
585  {
586  return bucket.val;
587  }
588  num3 = (int)((num3 + incr) % (long)(uint)array.Length);
589  }
590  while (bucket.hash_coll < 0 && ++num2 < array.Length);
591  return null;
592  }
593  set
594  {
595  Insert(key, value, add: false);
596  }
597  }
598 
602  public virtual bool IsReadOnly => false;
603 
607  public virtual bool IsFixedSize => false;
608 
612  public virtual bool IsSynchronized => false;
613 
616  public virtual ICollection Keys
617  {
618  get
619  {
620  if (keys == null)
621  {
622  keys = new KeyCollection(this);
623  }
624  return keys;
625  }
626  }
627 
630  public virtual ICollection Values
631  {
632  get
633  {
634  if (values == null)
635  {
636  values = new ValueCollection(this);
637  }
638  return values;
639  }
640  }
641 
644  public virtual object SyncRoot
645  {
646  get
647  {
648  if (_syncRoot == null)
649  {
650  Interlocked.CompareExchange<object>(ref _syncRoot, new object(), (object)null);
651  }
652  return _syncRoot;
653  }
654  }
655 
658  public virtual int Count => count;
659 
660  internal Hashtable(bool trash)
661  {
662  }
663 
665  public Hashtable()
666  : this(0, 1f)
667  {
668  }
669 
674  public Hashtable(int capacity)
675  : this(capacity, 1f)
676  {
677  }
678 
688  public Hashtable(int capacity, float loadFactor)
689  {
690  if (capacity < 0)
691  {
692  throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
693  }
694  if (!(loadFactor >= 0.1f) || !(loadFactor <= 1f))
695  {
696  throw new ArgumentOutOfRangeException("loadFactor", Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", 0.1, 1.0));
697  }
698  this.loadFactor = 0.72f * loadFactor;
699  double num = (float)capacity / this.loadFactor;
700  if (num > 2147483647.0)
701  {
702  throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
703  }
704  int num2 = (num > 3.0) ? HashHelpers.GetPrime((int)num) : 3;
705  buckets = new bucket[num2];
706  loadsize = (int)(this.loadFactor * (float)num2);
707  isWriterInProgress = false;
708  }
709 
721  [Obsolete("Please use Hashtable(int, float, IEqualityComparer) instead.")]
722  public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
723  : this(capacity, loadFactor)
724  {
725  if (hcp == null && comparer == null)
726  {
727  _keycomparer = null;
728  }
729  else
730  {
731  _keycomparer = new CompatibleComparer(comparer, hcp);
732  }
733  }
734 
744  public Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer)
745  : this(capacity, loadFactor)
746  {
747  _keycomparer = equalityComparer;
748  }
749 
755  [Obsolete("Please use Hashtable(IEqualityComparer) instead.")]
757  : this(0, 1f, hcp, comparer)
758  {
759  }
760 
764  public Hashtable(IEqualityComparer equalityComparer)
765  : this(0, 1f, equalityComparer)
766  {
767  }
768 
777  [Obsolete("Please use Hashtable(int, IEqualityComparer) instead.")]
779  : this(capacity, 1f, hcp, comparer)
780  {
781  }
782 
789  public Hashtable(int capacity, IEqualityComparer equalityComparer)
790  : this(capacity, 1f, equalityComparer)
791  {
792  }
793 
799  : this(d, 1f)
800  {
801  }
802 
811  public Hashtable(IDictionary d, float loadFactor)
812  : this(d, loadFactor, null)
813  {
814  }
815 
824  [Obsolete("Please use Hashtable(IDictionary, IEqualityComparer) instead.")]
826  : this(d, 1f, hcp, comparer)
827  {
828  }
829 
836  public Hashtable(IDictionary d, IEqualityComparer equalityComparer)
837  : this(d, 1f, equalityComparer)
838  {
839  }
840 
853  [Obsolete("Please use Hashtable(IDictionary, float, IEqualityComparer) instead.")]
855  : this(d?.Count ?? 0, loadFactor, hcp, comparer)
856  {
857  if (d == null)
858  {
859  throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
860  }
861  IDictionaryEnumerator enumerator = d.GetEnumerator();
862  while (enumerator.MoveNext())
863  {
864  Add(enumerator.Key, enumerator.Value);
865  }
866  }
867 
878  public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer)
879  : this(d?.Count ?? 0, loadFactor, equalityComparer)
880  {
881  if (d == null)
882  {
883  throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
884  }
885  IDictionaryEnumerator enumerator = d.GetEnumerator();
886  while (enumerator.MoveNext())
887  {
888  Add(enumerator.Key, enumerator.Value);
889  }
890  }
891 
898  {
899  HashHelpers.SerializationInfoTable.Add(this, info);
900  }
901 
902  private uint InitHash(object key, int hashsize, out uint seed, out uint incr)
903  {
904  uint result = seed = (uint)(GetHash(key) & int.MaxValue);
905  incr = 1 + seed * 101 % (uint)(hashsize - 1);
906  return result;
907  }
908 
916  public virtual void Add(object key, object value)
917  {
918  Insert(key, value, add: true);
919  }
920 
923  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
924  public virtual void Clear()
925  {
926  if (count != 0 || occupancy != 0)
927  {
929  isWriterInProgress = true;
930  for (int i = 0; i < buckets.Length; i++)
931  {
932  buckets[i].hash_coll = 0;
933  buckets[i].key = null;
934  buckets[i].val = null;
935  }
936  count = 0;
937  occupancy = 0;
938  UpdateVersion();
939  isWriterInProgress = false;
941  }
942  }
943 
946  public virtual object Clone()
947  {
948  bucket[] array = buckets;
949  Hashtable hashtable = new Hashtable(count, _keycomparer);
950  hashtable.version = version;
951  hashtable.loadFactor = loadFactor;
952  hashtable.count = 0;
953  int num = array.Length;
954  while (num > 0)
955  {
956  num--;
957  object key = array[num].key;
958  if (key != null && key != array)
959  {
960  hashtable[key] = array[num].val;
961  }
962  }
963  return hashtable;
964  }
965 
972  public virtual bool Contains(object key)
973  {
974  return ContainsKey(key);
975  }
976 
983  public virtual bool ContainsKey(object key)
984  {
985  if (key == null)
986  {
987  throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
988  }
989  bucket[] array = buckets;
990  uint seed;
991  uint incr;
992  uint num = InitHash(key, array.Length, out seed, out incr);
993  int num2 = 0;
994  int num3 = (int)(seed % (uint)array.Length);
995  bucket bucket;
996  do
997  {
998  bucket = array[num3];
999  if (bucket.key == null)
1000  {
1001  return false;
1002  }
1003  if ((bucket.hash_coll & int.MaxValue) == num && KeyEquals(bucket.key, key))
1004  {
1005  return true;
1006  }
1007  num3 = (int)((num3 + incr) % (long)(uint)array.Length);
1008  }
1009  while (bucket.hash_coll < 0 && ++num2 < array.Length);
1010  return false;
1011  }
1012 
1017  public virtual bool ContainsValue(object value)
1018  {
1019  if (value == null)
1020  {
1021  int num = buckets.Length;
1022  while (--num >= 0)
1023  {
1024  if (buckets[num].key != null && buckets[num].key != buckets && buckets[num].val == null)
1025  {
1026  return true;
1027  }
1028  }
1029  }
1030  else
1031  {
1032  int num2 = buckets.Length;
1033  while (--num2 >= 0)
1034  {
1035  object val = buckets[num2].val;
1036  if (val != null && val.Equals(value))
1037  {
1038  return true;
1039  }
1040  }
1041  }
1042  return false;
1043  }
1044 
1045  private void CopyKeys(Array array, int arrayIndex)
1046  {
1047  bucket[] array2 = buckets;
1048  int num = array2.Length;
1049  while (--num >= 0)
1050  {
1051  object key = array2[num].key;
1052  if (key != null && key != buckets)
1053  {
1054  array.SetValue(key, arrayIndex++);
1055  }
1056  }
1057  }
1058 
1059  private void CopyEntries(Array array, int arrayIndex)
1060  {
1061  bucket[] array2 = buckets;
1062  int num = array2.Length;
1063  while (--num >= 0)
1064  {
1065  object key = array2[num].key;
1066  if (key != null && key != buckets)
1067  {
1068  DictionaryEntry dictionaryEntry = new DictionaryEntry(key, array2[num].val);
1069  array.SetValue(dictionaryEntry, arrayIndex++);
1070  }
1071  }
1072  }
1073 
1084  public virtual void CopyTo(Array array, int arrayIndex)
1085  {
1086  if (array == null)
1087  {
1088  throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array"));
1089  }
1090  if (array.Rank != 1)
1091  {
1092  throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
1093  }
1094  if (arrayIndex < 0)
1095  {
1096  throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
1097  }
1098  if (array.Length - arrayIndex < Count)
1099  {
1100  throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
1101  }
1102  CopyEntries(array, arrayIndex);
1103  }
1104 
1105  internal virtual KeyValuePairs[] ToKeyValuePairsArray()
1106  {
1107  KeyValuePairs[] array = new KeyValuePairs[count];
1108  int num = 0;
1109  bucket[] array2 = buckets;
1110  int num2 = array2.Length;
1111  while (--num2 >= 0)
1112  {
1113  object key = array2[num2].key;
1114  if (key != null && key != buckets)
1115  {
1116  array[num++] = new KeyValuePairs(key, array2[num2].val);
1117  }
1118  }
1119  return array;
1120  }
1121 
1122  private void CopyValues(Array array, int arrayIndex)
1123  {
1124  bucket[] array2 = buckets;
1125  int num = array2.Length;
1126  while (--num >= 0)
1127  {
1128  object key = array2[num].key;
1129  if (key != null && key != buckets)
1130  {
1131  array.SetValue(array2[num].val, arrayIndex++);
1132  }
1133  }
1134  }
1135 
1136  private void expand()
1137  {
1138  int newsize = HashHelpers.ExpandPrime(buckets.Length);
1139  rehash(newsize, forceNewHashCode: false);
1140  }
1141 
1142  private void rehash()
1143  {
1144  rehash(buckets.Length, forceNewHashCode: false);
1145  }
1146 
1147  private void UpdateVersion()
1148  {
1149  version++;
1150  }
1151 
1152  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1153  private void rehash(int newsize, bool forceNewHashCode)
1154  {
1155  occupancy = 0;
1156  bucket[] newBuckets = new bucket[newsize];
1157  for (int i = 0; i < buckets.Length; i++)
1158  {
1159  bucket bucket = buckets[i];
1160  if (bucket.key != null && bucket.key != buckets)
1161  {
1162  int hashcode = (forceNewHashCode ? GetHash(bucket.key) : bucket.hash_coll) & int.MaxValue;
1163  putEntry(newBuckets, bucket.key, bucket.val, hashcode);
1164  }
1165  }
1167  isWriterInProgress = true;
1168  buckets = newBuckets;
1169  loadsize = (int)(loadFactor * (float)newsize);
1170  UpdateVersion();
1171  isWriterInProgress = false;
1173  }
1174 
1178  {
1179  return new HashtableEnumerator(this, 3);
1180  }
1181 
1185  {
1186  return new HashtableEnumerator(this, 3);
1187  }
1188 
1194  protected virtual int GetHash(object key)
1195  {
1196  if (_keycomparer != null)
1197  {
1198  return _keycomparer.GetHashCode(key);
1199  }
1200  return key.GetHashCode();
1201  }
1202 
1211  protected virtual bool KeyEquals(object item, object key)
1212  {
1213  if (buckets == item)
1214  {
1215  return false;
1216  }
1217  if (item == key)
1218  {
1219  return true;
1220  }
1221  if (_keycomparer != null)
1222  {
1223  return _keycomparer.Equals(item, key);
1224  }
1225  return item?.Equals(key) ?? false;
1226  }
1227 
1228  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1229  private void Insert(object key, object nvalue, bool add)
1230  {
1231  if (key == null)
1232  {
1233  throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
1234  }
1235  if (count >= loadsize)
1236  {
1237  expand();
1238  }
1239  else if (occupancy > loadsize && count > 100)
1240  {
1241  rehash();
1242  }
1243  uint seed;
1244  uint incr;
1245  uint num = InitHash(key, buckets.Length, out seed, out incr);
1246  int num2 = 0;
1247  int num3 = -1;
1248  int num4 = (int)(seed % (uint)buckets.Length);
1249  do
1250  {
1251  if (num3 == -1 && buckets[num4].key == buckets && buckets[num4].hash_coll < 0)
1252  {
1253  num3 = num4;
1254  }
1255  if (buckets[num4].key == null || (buckets[num4].key == buckets && (buckets[num4].hash_coll & 2147483648u) == 0L))
1256  {
1257  if (num3 != -1)
1258  {
1259  num4 = num3;
1260  }
1262  isWriterInProgress = true;
1263  buckets[num4].val = nvalue;
1264  buckets[num4].key = key;
1265  buckets[num4].hash_coll |= (int)num;
1266  count++;
1267  UpdateVersion();
1268  isWriterInProgress = false;
1270  if (num2 > 100 && HashHelpers.IsWellKnownEqualityComparer(_keycomparer) && (_keycomparer == null || !(_keycomparer is RandomizedObjectEqualityComparer)))
1271  {
1272  _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
1273  rehash(buckets.Length, forceNewHashCode: true);
1274  }
1275  return;
1276  }
1277  if ((buckets[num4].hash_coll & int.MaxValue) == num && KeyEquals(buckets[num4].key, key))
1278  {
1279  if (add)
1280  {
1281  throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", buckets[num4].key, key));
1282  }
1284  isWriterInProgress = true;
1285  buckets[num4].val = nvalue;
1286  UpdateVersion();
1287  isWriterInProgress = false;
1289  if (num2 > 100 && HashHelpers.IsWellKnownEqualityComparer(_keycomparer) && (_keycomparer == null || !(_keycomparer is RandomizedObjectEqualityComparer)))
1290  {
1291  _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
1292  rehash(buckets.Length, forceNewHashCode: true);
1293  }
1294  return;
1295  }
1296  if (num3 == -1 && buckets[num4].hash_coll >= 0)
1297  {
1298  buckets[num4].hash_coll |= int.MinValue;
1299  occupancy++;
1300  }
1301  num4 = (int)((num4 + incr) % (long)(uint)buckets.Length);
1302  }
1303  while (++num2 < buckets.Length);
1304  if (num3 != -1)
1305  {
1307  isWriterInProgress = true;
1308  buckets[num3].val = nvalue;
1309  buckets[num3].key = key;
1310  buckets[num3].hash_coll |= (int)num;
1311  count++;
1312  UpdateVersion();
1313  isWriterInProgress = false;
1315  if (buckets.Length > 100 && HashHelpers.IsWellKnownEqualityComparer(_keycomparer) && (_keycomparer == null || !(_keycomparer is RandomizedObjectEqualityComparer)))
1316  {
1317  _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
1318  rehash(buckets.Length, forceNewHashCode: true);
1319  }
1320  return;
1321  }
1322  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HashInsertFailed"));
1323  }
1324 
1325  private void putEntry(bucket[] newBuckets, object key, object nvalue, int hashcode)
1326  {
1327  uint num = 1 + (uint)(hashcode * 101) % (uint)(newBuckets.Length - 1);
1328  int num2 = (int)((uint)hashcode % (uint)newBuckets.Length);
1329  while (newBuckets[num2].key != null && newBuckets[num2].key != buckets)
1330  {
1331  if (newBuckets[num2].hash_coll >= 0)
1332  {
1333  newBuckets[num2].hash_coll |= int.MinValue;
1334  occupancy++;
1335  }
1336  num2 = (int)((num2 + num) % (long)(uint)newBuckets.Length);
1337  }
1338  newBuckets[num2].val = nvalue;
1339  newBuckets[num2].key = key;
1340  newBuckets[num2].hash_coll |= hashcode;
1341  }
1342 
1348  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1349  public virtual void Remove(object key)
1350  {
1351  if (key == null)
1352  {
1353  throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
1354  }
1355  uint seed;
1356  uint incr;
1357  uint num = InitHash(key, buckets.Length, out seed, out incr);
1358  int num2 = 0;
1359  int num3 = (int)(seed % (uint)buckets.Length);
1360  while (true)
1361  {
1362  bucket bucket = buckets[num3];
1363  if ((bucket.hash_coll & int.MaxValue) == num && KeyEquals(bucket.key, key))
1364  {
1365  break;
1366  }
1367  num3 = (int)((num3 + incr) % (long)(uint)buckets.Length);
1368  if (bucket.hash_coll >= 0 || ++num2 >= buckets.Length)
1369  {
1370  return;
1371  }
1372  }
1374  isWriterInProgress = true;
1375  buckets[num3].hash_coll &= int.MinValue;
1376  if (buckets[num3].hash_coll != 0)
1377  {
1378  buckets[num3].key = buckets;
1379  }
1380  else
1381  {
1382  buckets[num3].key = null;
1383  }
1384  buckets[num3].val = null;
1385  count--;
1386  UpdateVersion();
1387  isWriterInProgress = false;
1389  }
1390 
1396  [HostProtection(SecurityAction.LinkDemand, Synchronization = true)]
1397  public static Hashtable Synchronized(Hashtable table)
1398  {
1399  if (table == null)
1400  {
1401  throw new ArgumentNullException("table");
1402  }
1403  return new SyncHashtable(table);
1404  }
1405 
1412  [SecurityCritical]
1413  public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
1414  {
1415  if (info == null)
1416  {
1417  throw new ArgumentNullException("info");
1418  }
1419  lock (SyncRoot)
1420  {
1421  int num = version;
1422  info.AddValue("LoadFactor", loadFactor);
1423  info.AddValue("Version", version);
1424  IEqualityComparer equalityComparer = (IEqualityComparer)HashHelpers.GetEqualityComparerForSerialization(_keycomparer);
1425  if (equalityComparer == null)
1426  {
1427  info.AddValue("Comparer", null, typeof(IComparer));
1428  info.AddValue("HashCodeProvider", null, typeof(IHashCodeProvider));
1429  }
1430  else if (equalityComparer is CompatibleComparer)
1431  {
1432  CompatibleComparer compatibleComparer = equalityComparer as CompatibleComparer;
1433  info.AddValue("Comparer", compatibleComparer.Comparer, typeof(IComparer));
1434  info.AddValue("HashCodeProvider", compatibleComparer.HashCodeProvider, typeof(IHashCodeProvider));
1435  }
1436  else
1437  {
1438  info.AddValue("KeyComparer", equalityComparer, typeof(IEqualityComparer));
1439  }
1440  info.AddValue("HashSize", buckets.Length);
1441  object[] array = new object[count];
1442  object[] array2 = new object[count];
1443  CopyKeys(array, 0);
1444  CopyValues(array2, 0);
1445  info.AddValue("Keys", array, typeof(object[]));
1446  info.AddValue("Values", array2, typeof(object[]));
1447  if (version != num)
1448  {
1449  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
1450  }
1451  }
1452  }
1453 
1457  public virtual void OnDeserialization(object sender)
1458  {
1459  if (buckets != null)
1460  {
1461  return;
1462  }
1463  HashHelpers.SerializationInfoTable.TryGetValue(this, out SerializationInfo value);
1464  if (value == null)
1465  {
1466  throw new SerializationException(Environment.GetResourceString("Serialization_InvalidOnDeser"));
1467  }
1468  int num = 0;
1469  IComparer comparer = null;
1470  IHashCodeProvider hashCodeProvider = null;
1471  object[] array = null;
1472  object[] array2 = null;
1473  SerializationInfoEnumerator enumerator = value.GetEnumerator();
1474  while (enumerator.MoveNext())
1475  {
1476  switch (enumerator.Name)
1477  {
1478  case "LoadFactor":
1479  loadFactor = value.GetSingle("LoadFactor");
1480  break;
1481  case "HashSize":
1482  num = value.GetInt32("HashSize");
1483  break;
1484  case "KeyComparer":
1485  _keycomparer = (IEqualityComparer)value.GetValue("KeyComparer", typeof(IEqualityComparer));
1486  break;
1487  case "Comparer":
1488  comparer = (IComparer)value.GetValue("Comparer", typeof(IComparer));
1489  break;
1490  case "HashCodeProvider":
1491  hashCodeProvider = (IHashCodeProvider)value.GetValue("HashCodeProvider", typeof(IHashCodeProvider));
1492  break;
1493  case "Keys":
1494  array = (object[])value.GetValue("Keys", typeof(object[]));
1495  break;
1496  case "Values":
1497  array2 = (object[])value.GetValue("Values", typeof(object[]));
1498  break;
1499  }
1500  }
1501  loadsize = (int)(loadFactor * (float)num);
1502  if (_keycomparer == null && (comparer != null || hashCodeProvider != null))
1503  {
1504  _keycomparer = new CompatibleComparer(comparer, hashCodeProvider);
1505  }
1506  buckets = new bucket[num];
1507  if (array == null)
1508  {
1509  throw new SerializationException(Environment.GetResourceString("Serialization_MissingKeys"));
1510  }
1511  if (array2 == null)
1512  {
1513  throw new SerializationException(Environment.GetResourceString("Serialization_MissingValues"));
1514  }
1515  if (array.Length != array2.Length)
1516  {
1517  throw new SerializationException(Environment.GetResourceString("Serialization_KeyValueDifferentSizes"));
1518  }
1519  for (int i = 0; i < array.Length; i++)
1520  {
1521  if (array[i] == null)
1522  {
1523  throw new SerializationException(Environment.GetResourceString("Serialization_NullKey"));
1524  }
1525  Insert(array[i], array2[i], add: true);
1526  }
1527  version = value.GetInt32("Version");
1528  HashHelpers.SerializationInfoTable.Remove(this);
1529  }
1530  }
1531 }
Supplies a hash code for an object, using a custom hash function.
virtual bool IsSynchronized
Gets a value indicating whether access to the T:System.Collections.Hashtable is synchronized (thread ...
Definition: Hashtable.cs:612
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
Provides a base class for implementations of the T:System.Collections.Generic.IEqualityComparer`1 gen...
virtual void Add(object key, object value)
Adds an element with the specified key and value into the T:System.Collections.Hashtable.
Definition: Hashtable.cs:916
bool MoveNext()
Advances the enumerator to the next element of the collection.
Hashtable(int capacity)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:674
virtual IDictionaryEnumerator GetEnumerator()
Returns an T:System.Collections.IDictionaryEnumerator that iterates through the T:System....
Definition: Hashtable.cs:1184
Hashtable(SerializationInfo info, StreamingContext context)
Initializes a new, empty instance of the T:System.Collections.Hashtable class that is serializable us...
Definition: Hashtable.cs:897
Hashtable(IDictionary d, IEqualityComparer equalityComparer)
Initializes a new instance of the T:System.Collections.Hashtable class by copying the elements from t...
Definition: Hashtable.cs:836
object Key
Gets the key of the current dictionary entry.
Indicates that a class is to be notified when deserialization of the entire object graph has been com...
Hashtable(int capacity, float loadFactor)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:688
Definition: __Canon.cs:3
new IEnumerator< T > GetEnumerator()
Returns an enumerator that iterates through the collection.
The exception that is thrown when the value of an argument is outside the allowable range of values a...
virtual void GetObjectData(SerializationInfo info, StreamingContext context)
Implements the T:System.Runtime.Serialization.ISerializable interface and returns the data needed to ...
Definition: Hashtable.cs:1413
virtual object Clone()
Creates a shallow copy of the T:System.Collections.Hashtable.
Definition: Hashtable.cs:946
Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:722
Exposes the enumerator, which supports a simple iteration over a collection of a specified type....
Definition: IEnumerable.cs:9
virtual bool ContainsKey(object key)
Determines whether the T:System.Collections.Hashtable contains a specific key.
Definition: Hashtable.cs:983
Describes the source and destination of a given serialized stream, and provides an additional caller-...
virtual bool IsFixedSize
Gets a value indicating whether the T:System.Collections.Hashtable has a fixed size.
Definition: Hashtable.cs:607
virtual bool KeyEquals(object item, object key)
Compares a specific T:System.Object with a specific key in the T:System.Collections....
Definition: Hashtable.cs:1211
Supports a simple iteration over a generic collection.
Definition: IEnumerator.cs:6
IComparer comparer
Gets or sets the T:System.Collections.IComparer to use for the T:System.Collections....
Definition: Hashtable.cs:510
Cer
Specifies a method's behavior when called within a constrained execution region.
Definition: Cer.cs:5
virtual ICollection Values
Gets an T:System.Collections.ICollection containing the values in the T:System.Collections....
Definition: Hashtable.cs:631
virtual int GetHash(object key)
Returns the hash code for the specified key.
Definition: Hashtable.cs:1194
virtual void OnDeserialization(object sender)
Implements the T:System.Runtime.Serialization.ISerializable interface and raises the deserialization ...
Definition: Hashtable.cs:1457
SecurityAction
Specifies the security actions that can be performed using declarative security.
Exposes an enumerator, which supports a simple iteration over a non-generic collection....
Definition: IEnumerable.cs:9
Hashtable(IEqualityComparer equalityComparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the default initi...
Definition: Hashtable.cs:764
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
new bool Equals(object x, object y)
Determines whether the specified objects are equal.
virtual void CopyTo(Array array, int arrayIndex)
Copies the T:System.Collections.Hashtable elements to a one-dimensional T:System.Array instance at th...
Definition: Hashtable.cs:1084
Hashtable(IDictionary d)
Initializes a new instance of the T:System.Collections.Hashtable class by copying the elements from t...
Definition: Hashtable.cs:798
Hashtable(IDictionary d, float loadFactor)
Initializes a new instance of the T:System.Collections.Hashtable class by copying the elements from t...
Definition: Hashtable.cs:811
static int CompareExchange(ref int location1, int value, int comparand)
Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.
Represents a collection of key/value pairs that are organized based on the hash code of the key....
Definition: Hashtable.cs:17
virtual ICollection Keys
Gets an T:System.Collections.ICollection containing the keys in the T:System.Collections....
Definition: Hashtable.cs:617
Defines methods to support the comparison of objects for equality.
static void BeginCriticalRegion()
Notifies a host that execution is about to enter a region of code in which the effects of a thread ab...
Supports cloning, which creates a new instance of a class with the same value as an existing instance...
Definition: ICloneable.cs:7
Exposes a method that compares two objects.
Definition: IComparer.cs:8
IHashCodeProvider hcp
Gets or sets the object that can dispense hash codes.
Definition: Hashtable.cs:475
Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the ba...
Definition: Array.cs:17
static Hashtable Synchronized(Hashtable table)
Returns a synchronized (thread-safe) wrapper for the T:System.Collections.Hashtable.
Definition: Hashtable.cs:1397
The exception thrown when an error occurs during serialization or deserialization.
static void EndCriticalRegion()
Notifies a host that execution is about to enter a region of code in which the effects of a thread ab...
Hashtable(IDictionary d, IHashCodeProvider hcp, IComparer comparer)
Initializes a new instance of the T:System.Collections.Hashtable class by copying the elements from t...
Definition: Hashtable.cs:825
IEnumerator GetEnumerator()
Returns an enumerator that iterates through a collection.
Hashtable(IHashCodeProvider hcp, IComparer comparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the default initi...
Definition: Hashtable.cs:756
virtual bool ContainsValue(object value)
Determines whether the T:System.Collections.Hashtable contains a specific value.
Definition: Hashtable.cs:1017
Stores all the data needed to serialize or deserialize an object. This class cannot be inherited.
virtual object SyncRoot
Gets an object that can be used to synchronize access to the T:System.Collections....
Definition: Hashtable.cs:645
Hashtable(int capacity, IEqualityComparer equalityComparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:789
int GetHashCode(object obj)
Returns a hash code for the specified object.
The exception that is thrown when one of the arguments provided to a method is not valid.
Allows an object to control its own serialization and deserialization.
Definition: ISerializable.cs:8
virtual bool Contains(object key)
Determines whether the T:System.Collections.Hashtable contains a specific key.
Definition: Hashtable.cs:972
virtual void Remove(object key)
Removes the element with the specified key from the T:System.Collections.Hashtable.
Definition: Hashtable.cs:1349
new IDictionaryEnumerator GetEnumerator()
Returns an T:System.Collections.IDictionaryEnumerator object for the T:System.Collections....
object Value
Gets the value of the current dictionary entry.
virtual bool IsReadOnly
Gets a value indicating whether the T:System.Collections.Hashtable is read-only.
Definition: Hashtable.cs:602
Hashtable(int capacity, IHashCodeProvider hcp, IComparer comparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:778
Specifies that the class can be serialized.
Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer)
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the specified ini...
Definition: Hashtable.cs:744
Enumerates the elements of a nongeneric dictionary.
string Name
Gets the name for the item currently being examined.
The exception that is thrown when a method call is invalid for the object's current state.
Hashtable()
Initializes a new, empty instance of the T:System.Collections.Hashtable class using the default initi...
Definition: Hashtable.cs:665
Consistency
Specifies a reliability contract.
Definition: Consistency.cs:5
virtual void Clear()
Removes all elements from the T:System.Collections.Hashtable.
Definition: Hashtable.cs:924
Defines size, enumerators, and synchronization methods for all nongeneric collections.
Definition: ICollection.cs:8
static void Sleep(int millisecondsTimeout)
Suspends the current thread for the specified number of milliseconds.
Definition: Thread.cs:746
Defines a dictionary key/value pair that can be set or retrieved.
Provides a formatter-friendly mechanism for parsing the data in T:System.Runtime.Serialization....
DebuggerBrowsableState
Provides display instructions for the debugger.
Represents a nongeneric collection of key/value pairs.
Definition: IDictionary.cs:8
Provides atomic operations for variables that are shared by multiple threads.
Definition: Interlocked.cs:10
Supports a simple iteration over a non-generic collection.
Definition: IEnumerator.cs:9
virtual int Count
Gets the number of key/value pairs contained in the T:System.Collections.Hashtable.
Definition: Hashtable.cs:658
bool MoveNext()
Updates the enumerator to the next item.
Creates and controls a thread, sets its priority, and gets its status.
Definition: Thread.cs:18