Get list of active items from ConditionalWeakTable<T>
I ended up creating my own wrapper:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
public sealed class ConditionalHashSet<T> where T : class
{
private readonly object locker = new object();
private readonly List<WeakReference> weakList = new List<WeakReference>();
private readonly ConditionalWeakTable<T, WeakReference> weakDictionary =
new ConditionalWeakTable<T, WeakReference>();
public void Add(T item)
{
lock (this.locker)
{
var reference = new WeakReference(item);
this.weakDictionary.Add(item, reference);
this.weakList.Add(reference);
this.Shrink();
}
}
public void Remove(T item)
{
lock (this.locker)
{
WeakReference reference;
if (this.weakDictionary.TryGetValue(item, out reference))
{
reference.Target = null;
this.weakDictionary.Remove(item);
}
}
}
public T[] ToArray()
{
lock (this.locker)
{
return (
from weakReference in this.weakList
let item = (T)weakReference.Target
where item != null
select item)
.ToArray();
}
}
private void Shrink()
{
// This method prevents the List<T> from growing indefinitely, but
// might also cause a performance problem in some cases.
if (this.weakList.Capacity == this.weakList.Count)
{
this.weakList.RemoveAll(weak => !weak.IsAlive);
}
}
}
In some recent framework version, the ConditionalWeakTable<TKey,TValue>
now implements IEnumerator
interface. Check out Microsoft Docs.
This applies to
- .NET Core >=
2.0
- .NET Standard >=
2.1
This is not solving the problem if someone is stuck with .NET Framework. Otherwise, this may help if, like me, it's only a matter of updating from .NET Standard 2.0
to 2.1
.