C# - 获取对象的引用数

13 c# reflection resources reference resourcemanager

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

  • 当一个对象不再需要对资源的引用时,它必须调用资源管理器的方法来表示它不再使用它; 要么

  • 当一个对象不再需要对资源的引用时,它只是将其设置为null.然后,当要求资源管理器卸载未使用的资源时,它会获取每个资源的引用计数(通过反射?).如果引用计数为1(资源管理器将具有对资源的引用),则卸载资源.

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

Eri*_*ert 31

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

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

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


Mar*_*ell 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)
}
Run Code Online (Sandbox Code Playgroud)

  • `object` 足够强大以防止收集;要么是‘null’,要么是强。调用者必须将它转换为 *typed* 引用,但这是一个不同的问题...... (2认同)