我正在寻找一个好的模式来实现C#中的ref计数。我有一个
Dictionary<string, MyObject> ObjList;
我想要做的是分发对MyObject
个实例的引用(如果它们存在),如果不存在则创建新的实例。我的代码中的多个位置可能会引用MyObject
实例,但是当所有实例都被释放后,我想将它从我的字典中删除。我调查了WeakReference
,但我不确定它是否适用于此?
编辑1.) 细节我正在使用OPC服务器,因此每当我引用一个项目时,我都希望使用该字典来查找该项目的现有引用。当我不再需要该项目时,我想取消订阅该项目。很难知道我的代码当前使用该项目的时间或位置。
答案 0 :(得分:4)
我在这些场景中所做的是创建WeakReferences
字典。 WeakReference
的作用是允许您的字典引用MyObject
的实例而不将该实例保留在内存中。因此,一旦释放了对该对象的所有其他引用,该项目的条目仍将存在于字典中。但是,该条目会引用WeakReference
,其中IsAlive
为false
而Target
为null
。如果需要,您可以通过删除WeakReference
未生存的所有条目来偶尔清理字典。
答案 1 :(得分:1)
这是你需要的东西:
public class WeakReferences<T>
{
private Func<string, T> _factory;
public WeakReferences(Func<string, T> factory)
{
_factory = factory;
}
private Dictionary<string, WeakReference> _references =
new Dictionary<string, WeakReference>();
public T this[string index]
{
get
{
T target = default(T);
if (_references.ContainsKey(index))
{
var wr = _references[index];
target = (T)wr.Target;
if (wr.IsAlive)
{
Console.WriteLine("Reused: " + index);
return target;
}
}
target = _factory(index);
_references[index] = new WeakReference(target);
return target;
}
}
}
你可以像这样使用它:
Func<string, object> f = k =>
{
Console.WriteLine("Created: " + k);
return new object();
};
var wrs = new WeakReferences<object>(f);
var a = wrs["a"];
var b = wrs["b"];
a = wrs["a"];
b = wrs["b"];
a = null;
GC.Collect();
a = wrs["a"];
b = wrs["b"];
我运行的输出是:
Created: a
Created: b
Reused: a
Reused: b
Created: a
Reused: b