C# - 获取对象的引用数

时间:2009-11-06 09:20:06

标签: c# reflection resources reference resourcemanager

我正在尝试为我正在编写的小爱好游戏编写一个简单的资源管理器。此资源管理器需要执行的任务之一是卸载未使用的资源。我可以想到以两种方式做到这一点:

  • 当一个物体不再需要时 它必须是对资源的引用 调用资源管理器的方法 表示它不再使用它; 或

  • 当一个物体不再需要时 简单地说,参考资源 将其设置为null。然后当 要求资源管理器卸载 未使用的资源,它得到了 引用计数(通过反射?) 每个资源。如果引用计数 是一个(资源经理会 参考资源), 卸载资源。

有没有办法在C#中实现第二个解决方案? 感谢。

5 个答案:

答案 0 :(得分:31)

夫妻俩。首先,对象不参考计数;参考计数方案具有循环参考问题,其中两个对象相互引用但是否则是不可访问的,从而泄漏。 .NET使用标记和扫描方法,不使用引用计数。

其次,尽管使用弱引用的建议并不可怕,但它也不是一个扣篮。您出于性能原因正在构建缓存。 (我假设您对应用程序的性能特征进行仔细,经验,实际的研究已经令人信服地证明,为了获得可接受的性能,缓存策略是必要的;如果不是这样,那么您就是过早地做出这些决定。)缓存必须具有关于何时释放其资源的POLICY,否则就是内存泄漏。

您如何知道GC政策和您的政策是等效的政策? GC的设计并未考虑到特定的性能需求。也就是说,它旨在释放真正属于垃圾的资源,而不是为了达到您想到的任何特定性能目标。通过将决策委派给GC,您可以放弃根据性能需求调整缓存策略的能力。

答案 1 :(得分:12)

听起来你可以从资源管理器中使用WeakReference。 GC将完成剩下的工作。你需要做一点点投射,但它会很简单,并且会起作用。

class Manager {
    Dictionary<string, WeakReference> refs =
        new Dictionary<string, WeakReference>();
    public object this[string key] {
        get {
            WeakReference wr;
            if (refs.TryGetValue(key, out wr)) {
                if(wr.IsAlive) return wr.Target;
                refs.Remove(key);
            }
            return null;
        }
        set {
            refs[key] = new WeakReference(value);
        }
    }
}
static void Main() {
    Manager mgr = new Manager();
    var obj = new byte[1024];
    mgr["abc"] = obj;

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // true (still ref'd by "obj")

    obj = null;
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // false (no remaining refs)
}

答案 2 :(得分:2)

我们已经在.NET中有一个名为垃圾收集器的资源管理器。因此,一种非常有效的方法是将引用设置为null并且不执行任何操作。

更直接的答案:不,没有办法将参考文献转换为

您可能想要学习WeakReference class或使用缓存系统。

答案 3 :(得分:1)

确保资源管理器将WeakReference用于您的资源。这样,当没有其他人引用资源时,他们就有资格进行垃圾收集。

答案 4 :(得分:0)

正如其他用户已经说过的那样,您尝试实现的目标已经由GC完成,可以使用WeakReference进行微调。

这意味着在.NET,Java等托管环境中,这是一个无问题。

由于低级框架架构将您与内存管理隔离开来,如果您仍然需要这种功能,我强烈建议您查看自己的代码架构,因为这会意味着您正在做某种不好的事情 - 内存管理实践