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));
 }