C#引用计数

时间:2016-01-26 00:46:14

标签: c# .net dictionary reference

我正在寻找一个好的模式来实现C#中的ref计数。我有一个

Dictionary<string, MyObject> ObjList;

我想要做的是分发对MyObject个实例的引用(如果它们存在),如果不存在则创建新的实例。我的代码中的多个位置可能会引用MyObject实例,但是当所有实例都被释放后,我想将它从我的字典中删除。我调查了WeakReference,但我不确定它是否适用于此?

编辑1.) 细节我正在使用OPC服务器,因此每当我引用一个项目时,我都希望使用该字典来查找该项目的现有引用。当我不再需要该项目时,我想取消订阅该项目。很难知道我的代码当前使用该项目的时间或位置。

2 个答案:

答案 0 :(得分:4)

我在这些场景中所做的是创建WeakReferences字典。 WeakReference的作用是允许您的字典引用MyObject的实例而不将该实例保留在内存中。因此,一旦释放了对该对象的所有其他引用,该项目的条目仍将存在于字典中。但是,该条目会引用WeakReference,其中IsAlivefalseTargetnull。如果需要,您可以通过删除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