代码之家  ›  专栏  ›  技术社区  ›  Tim Lovell-Smith

有没有一种方法可以在clr中进行弱收集(比如weakreference)?

  •  16
  • Tim Lovell-Smith  · 技术社区  · 14 年前

    使用A List<WeakReference> 不会像我想的那样工作。我想要的是我们的关系自动 已从列表中删除 每当它们引用的对象被垃圾收集时。

    ConditionalWeakTable<TKey,TValue> 我也不满意,因为尽管它的键和值被弱引用和可收集,但您不能枚举它们!

    3 回复  |  直到 7 年前
        1
  •  8
  •   Stephen Cleary    14 年前

    我同意执行 WeakList<T> 可能,但我不认为 容易的 . 欢迎使用我的实现 here . 这个 WeakCollection<T> 课程取决于 WeakReference<T> ,这又取决于 SafeGCHandle .

        2
  •  8
  •   Thomas Levesque    14 年前

    您可以轻松实现 WeakList<T> 类,它将包装 List<WeakReference> .

    当对象被垃圾收集时,无法自动删除它们,因为无法检测何时发生这种情况。但是,您可以通过检查 WeakReference.IsAlive 财产。但是,我不推荐这种方法,因为从客户的角度来看,它可能会导致混乱的行为。相反,我建议实现 Purge 方法删除死条,您将显式调用该方法。

    下面是一个示例实现:

    public class WeakList<T> : IList<T>
    {
        private List<WeakReference<T>> _innerList = new List<WeakReference<T>>();
    
        #region IList<T> Members
    
        public int IndexOf(T item)
        {
            return _innerList.Select(wr => wr.Target).IndexOf(item);
        }
    
        public void Insert(int index, T item)
        {
            _innerList.Insert(index, new WeakReference<T>(item));
        }
    
        public void RemoveAt(int index)
        {
            _innerList.RemoveAt(index);
        }
    
        public T this[int index]
        {
            get
            {
                return _innerList[index].Target;
            }
            set
            {
                _innerList[index] = new WeakReference<T>(value);
            }
        }
    
        #endregion
    
        #region ICollection<T> Members
    
        public void Add(T item)
        {
            _innerList.Add(new WeakReference<T>(item));
        }
    
        public void Clear()
        {
            _innerList.Clear();
        }
    
        public bool Contains(T item)
        {
            return _innerList.Any(wr => object.Equals(wr.Target, item));
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            _innerList.Select(wr => wr.Target).CopyTo(array, arrayIndex);
        }
    
        public int Count
        {
            get { return _innerList.Count; }
        }
    
        public bool IsReadOnly
        {
            get { return false; }
        }
    
        public bool Remove(T item)
        {
            int index = IndexOf(item);
            if (index > -1)
            {
                RemoveAt(index);
                return true;
            }
            return false;
        }
    
        #endregion
    
        #region IEnumerable<T> Members
    
        public IEnumerator<T> GetEnumerator()
        {
            return _innerList.Select(x => x.Target).GetEnumerator();
        }
    
        #endregion
    
        #region IEnumerable Members
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    
        #endregion
    
        public void Purge()
        {
            _innerList.RemoveAll(wr => !wr.IsAlive);
        }
    }
    

    此类使用以下类和扩展方法:

    WeakReference<T> (只有一个强类型的包装 WeakReference )

    [Serializable]
    public class WeakReference<T> : WeakReference
    {
        public WeakReference(T target)
            : base(target)
        {
        }
    
        public WeakReference(T target, bool trackResurrection)
            : base(target, trackResurrection)
        {
        }
    
        public WeakReference(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    
        public new T Target
        {
            get
            {
                return (T)base.Target;
            }
        }
    }
    

    IndexOf (同) IList<T>.IndexOf ,但在 IEnumerable<T> )

        public static int IndexOf<T>(this IEnumerable<T> source, T item)
        {
            var entry = source.Select((x, i) => new { Value = x, Index = i })
                        .Where(x => object.Equals(x.Value, item))
                        .FirstOrDefault();
            return entry != null ? entry.Index : -1;
        }
    

    CopyTo (同) IList<T>.CopyTo ,但在 IEnumerable<t> )

        public static void CopyTo<T>(this IEnumerable<T> source, T[] array, int startIndex)
        {
            int lowerBound = array.GetLowerBound(0);
            int upperBound = array.GetUpperBound(0);
            if (startIndex < lowerBound)
                throw new ArgumentOutOfRangeException("startIndex", "The start index must be greater than or equal to the array lower bound");
            if (startIndex > upperBound)
                throw new ArgumentOutOfRangeException("startIndex", "The start index must be less than or equal to the array upper bound");
    
            int i = 0;
            foreach (var item in source)
            {
                if (startIndex + i > upperBound)
                    throw new ArgumentException("The array capacity is insufficient to copy all items from the source sequence");
                array[startIndex + i] = item;
                i++;
            }
        }
    
        3
  •  0
  •   Patrick Wolf    7 年前

    对于任何需要在.NET 2.0或3.5中使用ConditionalWeakTable的人,这里有一个反向端口: https://github.com/theraot/Theraot/wiki/Features