23 using System.Collections;
24 using System.Collections.Generic;
27 namespace Lucene.Net.Support
29 public sealed
class WeakDictionary<TKey, TValue> : IDictionary<TKey, TValue>
31 private HashMap<WeakKey<TKey>, TValue> _hm;
32 private int _gcCollections = 0;
34 public WeakDictionary(
int initialCapacity) : this(initialCapacity, Enumerable.Empty<KeyValuePair<TKey, TValue>>())
37 public WeakDictionary() : this(32, Enumerable.Empty<KeyValuePair<TKey, TValue>>())
40 public WeakDictionary(IEnumerable<KeyValuePair<TKey, TValue>> otherDictionary) : this(32, otherDictionary)
43 private WeakDictionary(
int initialCapacity, IEnumerable<KeyValuePair<TKey, TValue>> otherDict)
45 _hm =
new HashMap<WeakKey<TKey>, TValue>(initialCapacity);
46 foreach (var kvp
in otherDict)
48 _hm.Add(
new WeakKey<TKey>(kvp.Key), kvp.Value);
54 if (_hm.Count == 0)
return;
55 var newHm =
new HashMap<WeakKey<TKey>, TValue>();
56 foreach (var entry
in _hm.Where(x => x.Key != null && x.Key.IsAlive))
58 newHm.Add(entry.Key, entry.Value);
63 private void CleanIfNeeded()
65 int currentColCount = GC.CollectionCount(0);
66 if (currentColCount > _gcCollections)
69 _gcCollections = currentColCount;
73 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
75 foreach (var kvp
in _hm.Where(x => x.Key.IsAlive))
77 yield
return new KeyValuePair<TKey, TValue>(kvp.Key.Target, kvp.Value);
81 IEnumerator IEnumerable.GetEnumerator()
83 return GetEnumerator();
86 void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
89 ((ICollection<KeyValuePair<WeakKey<TKey>, TValue>>) _hm).Add(
90 new KeyValuePair<WeakKey<TKey>, TValue>(
new WeakKey<TKey>(item.Key), item.Value));
98 bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
100 return ((ICollection<KeyValuePair<WeakKey<TKey>, TValue>>)_hm).Contains(
101 new KeyValuePair<WeakKey<TKey>, TValue>(
new WeakKey<TKey>(item.Key), item.Value));
104 bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
106 return ((ICollection<KeyValuePair<WeakKey<TKey>, TValue>>)_hm).Remove(
107 new KeyValuePair<WeakKey<TKey>, TValue>(
new WeakKey<TKey>(item.Key), item.Value));
119 public bool IsReadOnly
121 get {
return false; }
124 public bool ContainsKey(TKey key)
126 return _hm.ContainsKey(
new WeakKey<TKey>(key));
129 public void Add(TKey key, TValue value)
132 _hm.Add(
new WeakKey<TKey>(key), value);
135 public bool Remove(TKey key)
137 return _hm.Remove(
new WeakKey<TKey>(key));
140 public bool TryGetValue(TKey key, out TValue value)
142 return _hm.TryGetValue(
new WeakKey<TKey>(key), out value);
145 public TValue
this[TKey key]
147 get {
return _hm[
new WeakKey<TKey>(key)]; }
151 _hm[
new WeakKey<TKey>(key)] = value;
155 public ICollection<TKey> Keys
160 return new KeyCollection(_hm);
164 public ICollection<TValue> Values
173 void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array,
int arrayIndex)
175 throw new NotSupportedException();
178 #region KeyCollection
179 class KeyCollection : ICollection<TKey>
181 private readonly HashMap<WeakKey<TKey>, TValue> _internalDict;
183 public KeyCollection(HashMap<WeakKey<TKey>, TValue> dict)
185 _internalDict = dict;
188 public IEnumerator<TKey> GetEnumerator()
190 foreach (var key
in _internalDict.Keys)
192 yield
return key.Target;
196 IEnumerator IEnumerable.GetEnumerator()
198 return GetEnumerator();
201 public void CopyTo(TKey[] array,
int arrayIndex)
203 throw new NotImplementedException(
"Implement this as needed");
208 get {
return _internalDict.Count + 1; }
211 public bool IsReadOnly
216 #region Explicit Interface Definitions
217 bool ICollection<TKey>.Contains(TKey item)
219 throw new NotSupportedException();
222 void ICollection<TKey>.Add(TKey item)
224 throw new NotSupportedException();
227 void ICollection<TKey>.Clear()
229 throw new NotSupportedException();
232 bool ICollection<TKey>.Remove(TKey item)
234 throw new NotSupportedException();
248 WeakReference reference;
251 public WeakKey(T key)
254 throw new ArgumentNullException(
"key");
256 hashCode = key.GetHashCode();
257 reference =
new WeakReference(key);
260 public override int GetHashCode()
265 public override bool Equals(
object obj)
267 if (!reference.IsAlive || obj == null)
return false;
269 if (
object.ReferenceEquals(
this, obj))
274 if (obj is WeakKey<T>)
276 var other = (WeakKey<T>)obj;
278 var referenceTarget = reference.Target;
279 return referenceTarget != null && referenceTarget.Equals(other.Target);
287 get {
return (T)reference.Target; }
292 get {
return reference.IsAlive; }