获得从ConditionalWeakTable&LT活跃的产品清单; T>清单、活跃、产品、ConditionalWeakTable

2023-09-03 21:47:49 作者:老子来虐菜

在.NET 4.0 ConditionalWeakTable< T> 是一个有效的字典,字典的键是弱引用,并且可以被收集,而这正是我需要的。问题是,我需要能够从该词典获得所有活键,但 MSDN状态的:

The .NET 4.0 ConditionalWeakTable<T> is effectively a dictionary where the dictionary's keys are weak referenced and can be collected, which is exactly what I need. The problem is that I need to be able to get all live keys from this dictionary, but MSDN states:

它不包括所有的方法(如的GetEnumerator或   包含)的一本字典一般了。

It does not include all the methods (such as GetEnumerator or Contains) that a dictionary typically has.

是否有可能检索来自现场​​的键或键值对的 ConditionalWeakTable&LT; T&GT;

Is there a possibility to retrieve the live keys or key-value pairs from a 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);
        }
    }
}