internal Container Resize(int newSize) { Debug.Assert(IsPowerOfTwo(newSize)); // Reallocate both buckets and entries and rebuild the bucket and entries from scratch. // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket. int[] newBuckets = new int[newSize]; for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++) { newBuckets[bucketIndex] = -1; } Entry[] newEntries = new Entry[newSize]; int newEntriesIndex = 0; // Migrate existing entries to the new table. for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) { int hashCode = _entries[entriesIndex].HashCode; DependentHandle depHnd = _entries[entriesIndex].depHnd; if (hashCode != -1 && depHnd.IsAllocated) { object primary, secondary; depHnd.GetPrimaryAndSecondary(out primary, out secondary); if (primary != null) { // Entry is used and has not expired. Link it into the appropriate bucket list. newEntries[newEntriesIndex].HashCode = hashCode; newEntries[newEntriesIndex].depHnd = depHnd; int bucket = hashCode & (newBuckets.Length - 1); newEntries[newEntriesIndex].Next = newBuckets[bucket]; newBuckets[bucket] = newEntriesIndex; newEntriesIndex++; } else { // Pretend the item was removed, so that this container's finalizer // will clean up this dependent handle. Volatile.Write(ref _entries[entriesIndex].HashCode, -1); } } } // Create the new container. We want to transfer the responsibility of freeing the handles from // the old container to the new container, and also ensure that the new container isn't finalized // while the old container may still be in use. As such, we store a reference from the old container // to the new one, which will keep the new container alive as long as the old one is. var newContainer = new Container(_parent, newBuckets, newEntries, newEntriesIndex); _oldKeepAlive = newContainer; // once this is set, the old container's finalizer will not free transferred dependent handles GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles. return(newContainer); }