public IEnumerator <KeyValuePair <TKey, TValue> > GetEnumerator() { if (m_capacity <= 0) { yield break; } Debug.Assert(m_entries != null); var version = m_version; for (int i = 0; i < m_entries.Length; i++) { var entry = m_entries[i]; if (!WeakDictionary <TKey, TValue> .IsFree(entry)) { TKey key; TValue value; if (entry.TryGetKeyValue(out key, out value)) { yield return(new KeyValuePair <TKey, TValue>(key, value)); } } if (version != m_version) { throw new InvalidOperationException(); } } }
private bool ContainsValue(TValue value) { if (m_size <= 0) { return(false); } Debug.Assert(m_entries != null); var comparer = EqualityComparer <TValue> .Default; for (int i = 0; i < m_entries.Length; i++) { var entry = m_entries[i]; if (WeakDictionary <TKey, TValue> .IsFree(entry)) { continue; } TKey targetKey; TValue targetValue; if (!entry.TryGetKeyValue(out targetKey, out targetValue)) { continue; } if (comparer.Equals(targetValue, value)) { return(true); } } return(false); }
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); }
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; } } }
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++; } }