使用 List<WeakReference>
不能满足我的要求。我希望 WeakReferences 在它们引用的对象被垃圾回收时能够自动从列表中 移除。
ConditionalWeakTable<TKey,TValue>
也无法满足我的要求,因为尽管其键和值是弱引用且可回收的,但您无法枚举它们!
使用 List<WeakReference>
不能满足我的要求。我希望 WeakReferences 在它们引用的对象被垃圾回收时能够自动从列表中 移除。
ConditionalWeakTable<TKey,TValue>
也无法满足我的要求,因为尽管其键和值是弱引用且可回收的,但您无法枚举它们!
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>
)
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++;
}
}
ConditionalWeakTable
将列表中的对象附加到具有终结器的其他对象上,以自动删除被GC回收的对象。请注意,不应该使用数字索引列表来完成此操作(因为没有办法以线程安全的方式完成删除),但是可以使用按创建顺序或反向顺序迭代事物的链接列表来完成此操作。然而,我不确定在哪些情况下主动删除成为死亡的引用... - supercatWeakReference
对象,但相对于上一次垃圾回收时存活的数量而言,其数量是有限的。 - supercatWeakReference<T>
https://msdn.microsoft.com/en-us/library/gg712738%28v=vs.110%29.aspx - chtenbWeakList<T>
是可能的,但我认为这并不是非常容易。您可以在此处使用我的实现。WeakCollection<T>
类依赖于WeakReference<T>
,而后者又依赖于SafeGCHandle
。对于任何需要在 .NET 2.0 或 3.5 中使用 ConditionalWeakTable 的人,可以在这里找到其后移版本:https://github.com/theraot/Theraot/wiki/Features
WeakReference
不应用于缓存; 有更好的解决方案(例如System.Runtime.Caching)。 - Stephen ClearyNito.Mvvm.WeakCollection<T>
by Stephen Cleary |Roslyn.Utilities.WeakList<T>
by Roslyn - Pang