1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
6 using System.Collections;
\r
7 using System.Collections.Generic;
\r
9 using Microsoft.Internal;
\r
10 using Microsoft.Internal.Collections;
\r
12 namespace Microsoft.Internal.Collections
\r
14 // This is a broken implementation of ConditionalWeakTable that allows us
\r
15 // to compile and work on versions of .Net eariler then 4.0. This class is
\r
16 // broken when there are circular dependencies between keys and values, which
\r
17 // can only be fixed by using some specific CLR 4.0 features.
\r
18 // For code samples of the broken behavior see ConditionalWeakTableTests.cs.
\r
19 internal class ConditionalWeakTable<TKey, TValue>
\r
21 where TValue : class
\r
23 private readonly Dictionary<object, TValue> _table;
\r
24 private int _capacity = 4;
\r
26 public ConditionalWeakTable()
\r
28 this._table = new Dictionary<object, TValue>();
\r
31 public void Add(TKey key, TValue value)
\r
33 CleanupDeadReferences();
\r
34 this._table.Add(CreateWeakKey(key), value);
\r
37 public bool Remove(TKey key)
\r
39 return this._table.Remove(key);
\r
42 public bool TryGetValue(TKey key, out TValue value)
\r
44 return this._table.TryGetValue(key, out value);
\r
47 private void CleanupDeadReferences()
\r
49 if (this._table.Count < _capacity)
\r
54 object[] deadKeys = this._table.Keys
\r
55 .Where(weakRef => !((EquivalentWeakReference)weakRef).IsAlive).ToArray();
\r
57 foreach (var deadKey in deadKeys)
\r
59 this._table.Remove(deadKey);
\r
62 if (this._table.Count >= _capacity)
\r
68 private static object CreateWeakKey(TKey key)
\r
70 return new EquivalentWeakReference(key);
\r
73 private class EquivalentWeakReference
\r
75 private readonly WeakReference _weakReference;
\r
76 private readonly int _hashCode;
\r
78 public EquivalentWeakReference(object obj)
\r
80 this._hashCode = obj.GetHashCode();
\r
81 this._weakReference = new WeakReference(obj);
\r
88 return this._weakReference.IsAlive;
\r
92 public override bool Equals(object obj)
\r
94 EquivalentWeakReference weakRef = obj as EquivalentWeakReference;
\r
96 if (weakRef != null)
\r
98 obj = weakRef._weakReference.Target;
\r
103 return base.Equals(weakRef);
\r
106 return object.Equals(this._weakReference.Target, obj);
\r
109 public override int GetHashCode()
\r
111 return this._hashCode;
\r