private bool FindKey(TKey key, out int bucket, out int index, out int previous, out TValue value) { Debug.Assert(!object.ReferenceEquals(key, null)); bucket = -1; index = -1; previous = -1; value = default(TValue); if (m_size <= 0) { return(false); } Debug.Assert(m_buckets != null); Debug.Assert(m_entries != null); Debug.Assert(m_entriesInfo != null); var hashCode = m_comparer.GetHashCode(key); bucket = this.GetBucket(hashCode); Debug.Assert((bucket >= 0) && (bucket < m_buckets.Length)); index = m_buckets[bucket]; previous = -1; while (index >= 0) { var entryInfo = m_entriesInfo[index]; if (entryInfo.HashCode == hashCode) { TKey targetKey; var entry = m_entries[index]; Debug.Assert(!WeakDictionary <TKey, TValue> .IsFree(entry)); if (entry.TryGetKeyValue(out targetKey, out value) && m_comparer.Equals(targetKey, key)) { return(true); } } previous = index; index = entryInfo.Next; } bucket = -1; index = -1; previous = -1; return(false); }
internal WeakDictionary(int capacity, IEqualityComparer <TKey> comparer) { if (capacity < 0) { throw new ArgumentOutOfRangeException("capacity"); } if (capacity > 0) { this.EnsureCapacity(capacity); } m_comparer = comparer ?? EqualityComparer <TKey> .Default; m_creator = WeakDictionary <TKey, TValue> .GetCreator(); Debug.Assert(m_comparer != null); Debug.Assert(m_creator != null); }
private void RemoveDeadEntries() { if (m_capacity <= 0) { return; } Debug.Assert(m_buckets != null); Debug.Assert(m_entries != null); Debug.Assert(m_entriesInfo != null); for (int bucket = 0; bucket < m_buckets.Length; bucket++) { var index = m_buckets[bucket]; var previous = -1; while (index >= 0) { var entry = m_entries[index]; var entryInfo = m_entriesInfo[index]; var next = entryInfo.Next; Debug.Assert(!WeakDictionary <TKey, TValue> .IsFree(entry)); TKey targetKey; TValue targetValue; if (!entry.TryGetKeyValue(out targetKey, out targetValue)) { this.RemoveCore(bucket, index, previous); } else { previous = index; } index = next; } } }
internal ValueCollection(WeakDictionary <TKey, TValue> owner) { Debug.Assert(owner != null); m_owner = owner; }
private void EnsureCapacity(long min) { if ((m_capacity >= min) && (m_capacity > 0)) { return; } this.RemoveDeadEntries(); if (m_size * 2L < m_capacity) { return; } var capacity = WeakDictionary <TKey, TValue> .FindNextSize(min); Debug.Assert(capacity > 0); m_buckets = new int[capacity]; Array.Resize(ref m_entries, capacity); Array.Resize(ref m_entriesInfo, capacity); for (int i = 0; i < m_buckets.Length; i++) { m_buckets[i] = -1; } for (int i = m_capacity; i < capacity; i++) { m_entries[i] = null; m_entriesInfo[i] = new EntryInfo((i < capacity - 1) ? i + 1 : -1); } // Rehash the elements to initialize the buckets. for (int i = 0; i < m_capacity; i++) { // Do not rehash free entries. if (WeakDictionary <TKey, TValue> .IsFree(m_entries[i])) { continue; } var entryInfo = m_entriesInfo[i]; var bucket = WeakDictionary <TKey, TValue> .GetBucket(entryInfo.HashCode, capacity); Debug.Assert((bucket >= 0) && (bucket < capacity)); var index = m_buckets[bucket]; m_buckets[bucket] = i; m_entriesInfo[i] = entryInfo.SetNext(index); } // Link the remaining free entries to the newly created free entries. if (m_free >= 0) { var index = m_free; while (true) { var next = m_entriesInfo[index].Next; if (next < 0) { m_entriesInfo[index] = new EntryInfo(m_capacity); break; } index = next; } } else { m_free = m_capacity; } m_capacity = capacity; unchecked { m_version++; } }
private int GetBucket(int hashCode) { return(WeakDictionary <TKey, TValue> .GetBucket(hashCode, m_capacity)); }