summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Collections/Hashtable.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Collections/Hashtable.cs')
-rw-r--r--src/mscorlib/src/System/Collections/Hashtable.cs323
1 files changed, 9 insertions, 314 deletions
diff --git a/src/mscorlib/src/System/Collections/Hashtable.cs b/src/mscorlib/src/System/Collections/Hashtable.cs
index d4c7d8d673..d1831dd97d 100644
--- a/src/mscorlib/src/System/Collections/Hashtable.cs
+++ b/src/mscorlib/src/System/Collections/Hashtable.cs
@@ -17,7 +17,6 @@ namespace System.Collections {
using System;
using System.Runtime;
using System.Runtime.Serialization;
- using System.Security.Permissions;
using System.Diagnostics;
using System.Threading;
using System.Runtime.CompilerServices;
@@ -66,9 +65,8 @@ namespace System.Collections {
//
[DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))]
[DebuggerDisplay("Count = {Count}")]
- [System.Runtime.InteropServices.ComVisible(true)]
[Serializable]
- public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable {
+ internal class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable {
/*
Implementation Notes:
The generic Dictionary was copied from Hashtable's source - any bug
@@ -165,75 +163,6 @@ namespace System.Collections {
private IEqualityComparer _keycomparer;
private Object _syncRoot;
- [Obsolete("Please use EqualityComparer property.")]
- protected IHashCodeProvider hcp
- {
- get
- {
- if( _keycomparer is CompatibleComparer) {
- return ((CompatibleComparer)_keycomparer).HashCodeProvider;
- }
- else if( _keycomparer == null) {
- return null;
- }
- else {
- throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
- }
- }
- set
- {
- if (_keycomparer is CompatibleComparer) {
- CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
- _keycomparer = new CompatibleComparer(keyComparer.Comparer, value);
- }
- else if( _keycomparer == null) {
- _keycomparer = new CompatibleComparer((IComparer)null, value);
- }
- else {
- throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
- }
- }
- }
-
-
- [Obsolete("Please use KeyComparer properties.")]
- protected IComparer comparer
- {
- get
- {
- if( _keycomparer is CompatibleComparer) {
- return ((CompatibleComparer)_keycomparer).Comparer;
- }
- else if( _keycomparer == null) {
- return null;
- }
- else {
- throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
- }
- }
- set
- {
- if (_keycomparer is CompatibleComparer) {
- CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
- _keycomparer = new CompatibleComparer(value, keyComparer.HashCodeProvider);
- }
- else if( _keycomparer == null) {
- _keycomparer = new CompatibleComparer(value, (IHashCodeProvider)null);
- }
- else {
- throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
- }
- }
- }
-
- protected IEqualityComparer EqualityComparer
- {
- get
- {
- return _keycomparer;
- }
- }
-
// Note: this constructor is a bogus constructor that does nothing
// and is for use only with SyncHashtable.
internal Hashtable( bool trash )
@@ -290,126 +219,31 @@ namespace System.Collections {
Debug.Assert( loadsize < hashsize, "Invalid hashtable loadsize!");
}
- // Constructs a new hashtable with the given initial capacity and load
- // factor. The capacity argument serves as an indication of the
- // number of entries the hashtable will contain. When this number (or an
- // approximation) is known, specifying it in the constructor can eliminate
- // a number of resizing operations that would otherwise be performed when
- // elements are added to the hashtable. The loadFactor argument
- // indicates the maximum ratio of hashtable entries to hashtable buckets.
- // Smaller load factors cause faster average lookup times at the cost of
- // increased memory consumption. A load factor of 1.0 generally provides
- // the best balance between speed and size. The hcp argument
- // is used to specify an Object that will provide hash codes for all
- // the Objects in the table. Using this, you can in effect override
- // GetHashCode() on each Object using your own hash function. The
- // comparer argument will let you specify a custom function for
- // comparing keys. By specifying user-defined objects for hcp
- // and comparer, users could make a hash table using strings
- // as keys do case-insensitive lookups.
- //
- [Obsolete("Please use Hashtable(int, float, IEqualityComparer) instead.")]
- public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer) : this(capacity, loadFactor) {
- if (hcp == null && comparer == null) {
- this._keycomparer = null;
- }
- else {
- this._keycomparer = new CompatibleComparer(comparer,hcp);
- }
- }
-
public Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer) : this(capacity, loadFactor) {
this._keycomparer = equalityComparer;
}
-
- // Constructs a new hashtable using a custom hash function
- // and a custom comparison function for keys. This will enable scenarios
- // such as doing lookups with case-insensitive strings.
- //
- [Obsolete("Please use Hashtable(IEqualityComparer) instead.")]
- public Hashtable(IHashCodeProvider hcp, IComparer comparer) : this(0, 1.0f, hcp, comparer) {
- }
public Hashtable(IEqualityComparer equalityComparer) : this(0, 1.0f, equalityComparer) {
}
-
- // Constructs a new hashtable using a custom hash function
- // and a custom comparison function for keys. This will enable scenarios
- // such as doing lookups with case-insensitive strings.
- //
- [Obsolete("Please use Hashtable(int, IEqualityComparer) instead.")]
- public Hashtable(int capacity, IHashCodeProvider hcp, IComparer comparer)
- : this(capacity, 1.0f, hcp, comparer) {
- }
public Hashtable(int capacity, IEqualityComparer equalityComparer)
: this(capacity, 1.0f, equalityComparer) {
}
-
- // Constructs a new hashtable containing a copy of the entries in the given
- // dictionary. The hashtable is created with a load factor of 1.0.
- //
- public Hashtable(IDictionary d) : this(d, 1.0f) {
- }
-
- // Constructs a new hashtable containing a copy of the entries in the given
- // dictionary. The hashtable is created with the given load factor.
- //
- public Hashtable(IDictionary d, float loadFactor)
- : this(d, loadFactor, (IEqualityComparer)null) {
- }
-
- [Obsolete("Please use Hashtable(IDictionary, IEqualityComparer) instead.")]
- public Hashtable(IDictionary d, IHashCodeProvider hcp, IComparer comparer)
- : this(d, 1.0f, hcp, comparer) {
- }
-
- public Hashtable(IDictionary d, IEqualityComparer equalityComparer)
- : this(d, 1.0f, equalityComparer) {
- }
- [Obsolete("Please use Hashtable(IDictionary, float, IEqualityComparer) instead.")]
- public Hashtable(IDictionary d, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
- : this((d != null ? d.Count : 0), loadFactor, hcp, comparer) {
- if (d==null)
- throw new ArgumentNullException(nameof(d), Environment.GetResourceString("ArgumentNull_Dictionary"));
- Contract.EndContractBlock();
-
- IDictionaryEnumerator e = d.GetEnumerator();
- while (e.MoveNext()) Add(e.Key, e.Value);
- }
-
- public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer)
- : this((d != null ? d.Count : 0), loadFactor, equalityComparer) {
- if (d==null)
- throw new ArgumentNullException(nameof(d), Environment.GetResourceString("ArgumentNull_Dictionary"));
- Contract.EndContractBlock();
-
- IDictionaryEnumerator e = d.GetEnumerator();
- while (e.MoveNext()) Add(e.Key, e.Value);
- }
-
- protected Hashtable(SerializationInfo info, StreamingContext context) {
- //We can't do anything with the keys and values until the entire graph has been deserialized
- //and we have a reasonable estimate that GetHashCode is not going to fail. For the time being,
- //we'll just cache this. The graph is not valid until OnDeserialization has been called.
- HashHelpers.SerializationInfoTable.Add(this, info);
- }
-
- // ‘InitHash’ is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
+ // InitHash is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
//
- // 1) The only ‘correctness’ requirement is that the ‘increment’ used to probe
+ // 1) The only correctness requirement is that the increment used to probe
// a. Be non-zero
- // b. Be relatively prime to the table size ‘hashSize’. (This is needed to insure you probe all entries in the table before you ‘wrap’ and visit entries already probed)
+ // b. Be relatively prime to the table size hashSize. (This is needed to insure you probe all entries in the table before you wrap and visit entries already probed)
// 2) Because we choose table sizes to be primes, we just need to insure that the increment is 0 < incr < hashSize
//
// Thus this function would work: Incr = 1 + (seed % (hashSize-1))
//
- // While this works well for ‘uniformly distributed’ keys, in practice, non-uniformity is common.
- // In particular in practice we can see ‘mostly sequential’ where you get long clusters of keys that ‘pack’.
- // To avoid bad behavior you want it to be the case that the increment is ‘large’ even for ‘small’ values (because small
- // values tend to happen more in practice). Thus we multiply ‘seed’ by a number that will make these small values
- // bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if ‘hashSize-1’ is not a multiple of HashPrime
+ // While this works well for uniformly distributed keys, in practice, non-uniformity is common.
+ // In particular in practice we can see mostly sequential where you get long clusters of keys that pack.
+ // To avoid bad behavior you want it to be the case that the increment is large even for small values (because small
+ // values tend to happen more in practice). Thus we multiply seed by a number that will make these small values
+ // bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if hashSize-1 is not a multiple of HashPrime
// (enforced in GetPrime), then incr has the potential of being every value from 1 to hashSize-1. The choice was largely arbitrary.
//
// Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize).
@@ -439,7 +273,6 @@ namespace System.Collections {
}
// Removes all entries from this hashtable.
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public virtual void Clear() {
Debug.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
@@ -517,29 +350,6 @@ namespace System.Collections {
} while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
return false;
}
-
- // Checks if this hashtable contains an entry with the given value. The
- // values of the entries of the hashtable are compared to the given value
- // using the Object.Equals method. This method performs a linear
- // search and is thus be substantially slower than the ContainsKey
- // method.
- //
- public virtual bool ContainsValue(Object value) {
-
- if (value == null) {
- for (int i = buckets.Length; --i >= 0;) {
- if (buckets[i].key != null && buckets[i].key != buckets && buckets[i].val == null)
- return true;
- }
- }
- else {
- for (int i = buckets.Length; --i >= 0;) {
- Object val = buckets[i].val;
- if (val!=null && val.Equals(value)) return true;
- }
- }
- return false;
- }
// Copies the keys of this hashtable to a given array starting at a given
// index. This method is used by the implementation of the CopyTo method in
@@ -590,25 +400,6 @@ namespace System.Collections {
CopyEntries(array, arrayIndex);
}
- // Copies the values in this Hashtable to an KeyValuePairs array.
- // KeyValuePairs is different from Dictionary Entry in that it has special
- // debugger attributes on its fields.
-
- internal virtual KeyValuePairs[] ToKeyValuePairsArray() {
-
- KeyValuePairs[] array = new KeyValuePairs[count];
- int index = 0;
- bucket[] lbuckets = buckets;
- for (int i = lbuckets.Length; --i >= 0;) {
- Object keyv = lbuckets[i].key;
- if ((keyv != null) && (keyv != buckets)){
- array[index++] = new KeyValuePairs(keyv,lbuckets[i].val);
- }
- }
-
- return array;
- }
-
// Copies the values of this hashtable to a given array starting at a given
// index. This method is used by the implementation of the CopyTo method in
@@ -720,7 +511,6 @@ namespace System.Collections {
version++;
}
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private void rehash( int newsize, bool forceNewHashCode ) {
// reset occupancy
@@ -853,7 +643,6 @@ namespace System.Collections {
// Inserts an entry into this hashtable. This method is called from the Set
// and Add methods. If the add parameter is true and the given key already
// exists in the hashtable, an exception is thrown.
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private void Insert (Object key, Object nvalue, bool add) {
if (key == null) {
throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key"));
@@ -987,7 +776,6 @@ namespace System.Collections {
// key exists in the hashtable, it is removed. An ArgumentException is
// thrown if the key is null.
//
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public virtual void Remove(Object key) {
if (key == null) {
throw new ArgumentNullException(nameof(key), Environment.GetResourceString("ArgumentNull_Key"));
@@ -1293,13 +1081,6 @@ namespace System.Collections {
internal SyncHashtable(Hashtable table) : base(false) {
_table = table;
}
-
- internal SyncHashtable(SerializationInfo info, StreamingContext context) : base (info, context) {
- _table = (Hashtable)info.GetValue("ParentTable", typeof(Hashtable));
- if (_table==null) {
- throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
- }
- }
/*================================GetObjectData=================================
@@ -1379,12 +1160,6 @@ namespace System.Collections {
return _table.ContainsKey(key);
}
- public override bool ContainsValue(Object key) {
- lock(_table.SyncRoot) {
- return _table.ContainsValue(key);
- }
- }
-
public override void CopyTo(Array array, int arrayIndex) {
lock (_table.SyncRoot) {
_table.CopyTo(array, arrayIndex);
@@ -1438,10 +1213,6 @@ namespace System.Collections {
public override void OnDeserialization(Object sender) {
return;
}
-
- internal override KeyValuePairs[] ToKeyValuePairsArray() {
- return _table.ToKeyValuePairsArray();
- }
}
@@ -1539,23 +1310,6 @@ namespace System.Collections {
// internal debug view class for hashtable
internal class HashtableDebugView {
private Hashtable hashtable;
-
- public HashtableDebugView( Hashtable hashtable) {
- if( hashtable == null) {
- throw new ArgumentNullException(nameof(hashtable));
- }
- Contract.EndContractBlock();
-
- this.hashtable = hashtable;
- }
-
-
- [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public KeyValuePairs[] Items {
- get {
- return hashtable.ToKeyValuePairsArray();
- }
- }
}
}
@@ -1605,7 +1359,6 @@ namespace System.Collections {
}
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsPrime(int candidate)
{
if ((candidate & 1) != 0)
@@ -1621,7 +1374,6 @@ namespace System.Collections {
return (candidate == 2);
}
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static int GetPrime(int min)
{
if (min < 0)
@@ -1644,11 +1396,6 @@ namespace System.Collections {
return min;
}
- public static int GetMinPrime()
- {
- return primes[0];
- }
-
// Returns size of hashtable to grow to.
public static int ExpandPrime(int oldSize)
{
@@ -1670,33 +1417,6 @@ namespace System.Collections {
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
#if FEATURE_RANDOMIZED_STRING_HASHING
- public static bool IsWellKnownEqualityComparer(object comparer)
- {
- return (comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);
- }
-
- public static IEqualityComparer GetRandomizedEqualityComparer(object comparer)
- {
- Debug.Assert(comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);
-
- if(comparer == null) {
- return new System.Collections.Generic.RandomizedObjectEqualityComparer();
- }
-
- if(comparer == System.Collections.Generic.EqualityComparer<string>.Default) {
- return new System.Collections.Generic.RandomizedStringEqualityComparer();
- }
-
- IWellKnownStringEqualityComparer cmp = comparer as IWellKnownStringEqualityComparer;
-
- if(cmp != null) {
- return cmp.GetRandomizedEqualityComparer();
- }
-
- Debug.Assert(false, "Missing case in GetRandomizedEqualityComparer!");
-
- return null;
- }
public static object GetEqualityComparerForSerialization(object comparer)
{
@@ -1716,33 +1436,8 @@ namespace System.Collections {
}
private const int bufferSize = 1024;
- private static byte[] data;
private static int currentIndex = bufferSize;
private static readonly object lockObj = new Object();
-
- internal static long GetEntropy()
- {
- lock(lockObj) {
- long ret;
-
- if(currentIndex == bufferSize)
- {
- if(data == null)
- {
- data = new byte[bufferSize];
- Debug.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8");
- }
-
- Microsoft.Win32.Win32Native.Random(true, data, data.Length);
- currentIndex = 0;
- }
-
- ret = BitConverter.ToInt64(data, currentIndex);
- currentIndex += 8;
-
- return ret;
- }
- }
#endif // FEATURE_RANDOMIZED_STRING_HASHING
}
}