public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer) { if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity", "negative capacity"); } if (loadFactor < 0.1f || loadFactor > 1.0f || Single.IsNaN(loadFactor)) { throw new ArgumentOutOfRangeException("loadFactor", "load factor"); } if (capacity == 0) { ++capacity; } this.loadFactor = 0.75f * loadFactor; double tableSize = capacity / this.loadFactor; if (tableSize > Int32.MaxValue) { throw new ArgumentException("Size is too big"); } int size = (int)tableSize; size = HashPrimeNumbers.ToPrime(size); this.SetTable(new Slot [size], new int [size]); this.hcp = hcp; this.comparer = comparer; this.inUse = 0; this.modificationCount = 0; }
private void Rehash() { int oldSize = this.table.Length; // From the SDK docs: // Hashtable is automatically increased // to the smallest prime number that is larger // than twice the current number of Hashtable buckets uint newSize = (uint)HashPrimeNumbers.ToPrime((oldSize << 1) | 1); Slot [] newTable = new Slot [newSize]; Slot [] table = this.table; int [] newHashes = new int [newSize]; int [] hashes = this.hashes; for (int i = 0; i < oldSize; i++) { Slot s = table [i]; if (s.key != null) { int h = hashes [i] & Int32.MaxValue; uint spot = (uint)h; uint step = ((uint)(h >> 5) + 1) % (newSize - 1) + 1; for (uint j = spot % newSize;; spot += step, j = spot % newSize) { // No check for KeyMarker.Removed here, // because the table is just allocated. if (newTable [j].key == null) { newTable [j].key = s.key; newTable [j].value = s.value; newHashes [j] |= h; break; } else { newHashes [j] |= CHAIN_MARKER; } } } } ++this.modificationCount; this.SetTable(newTable, newHashes); }
public virtual void OnDeserialization(object sender) { if (serializationInfo == null) { return; } loadFactor = (float)serializationInfo.GetValue("LoadFactor", typeof(float)); modificationCount = (int)serializationInfo.GetValue("Version", typeof(int)); try { equalityComparer = (IEqualityComparer)serializationInfo.GetValue("KeyComparer", typeof(object)); } catch { // If not found, try to get "Comparer" } if (equalityComparer == null) { comparerRef = (IComparer)serializationInfo.GetValue("Comparer", typeof(object)); } try { hcpRef = (IHashCodeProvider)serializationInfo.GetValue("HashCodeProvider", typeof(object)); } catch {} // Missing value => null int size = (int)serializationInfo.GetValue("HashSize", typeof(int)); Object [] keys = (Object [])serializationInfo.GetValue("Keys", typeof(Object [])); Object [] values = (Object [])serializationInfo.GetValue("Values", typeof(Object [])); if (keys.Length != values.Length) { throw new SerializationException("Keys and values of uneven size"); } size = HashPrimeNumbers.ToPrime(size); this.SetTable(new Slot [size], new int [size]); for (int i = 0; i < keys.Length; i++) { Add(keys[i], values[i]); } AdjustThreshold(); serializationInfo = null; }