C# - 获取对对象的引用数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1686416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:59:29  来源:igfitidea点击:

C# - Get number of references to object

c#reflectionresourcesreferenceresourcemanager

提问by

I'm trying to write a simple Resource Manager for the little hobby game I'm writing. One of the tasks that this resource manager needs to do is unloading unused resources. I can think of doing this in two ways:

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

  • When an object no longer requires a reference to the resource, it must call a method of the Resource Manager to signify it is no longer using it; or

  • When an object no longer requires a reference to the resource, it simply sets it to null. Then when the Resource Manager is asked to unload unused resources, it gets the reference count (via reflection?) of each resource. If the reference count is one (the Resource Manager will have a reference to the resource), unload the resource.

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

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

Is there any way to acheive the second solution in C#? Thanks.

有什么办法可以在 C# 中实现第二种解决方案吗?谢谢。

采纳答案by Marc Gravell

It sounds to me that you could just use WeakReferencefrom the resource manager. The GC will do the rest. You'll need to do a little casting, but it will be simple, and will work.

在我看来,您可以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)
}

回答by Henk Holterman

We already have a resource manager in .NET, called the Garbage collector. So a very efficient approach is to set the references to null and do nothing.

我们在 .NET 中已经有一个资源管理器,称为垃圾收集器。所以一个非常有效的方法是将引用设置为 null 并且什么都不做。

A more direct answer: No, there is no way to get the references toan object.

更直接的回答:没有,有没有办法让引用的对象。

You may want to study the WeakReference classor use a Caching system.

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

回答by Kent Boogaart

Ensure the resource manager uses WeakReferences to your resources. That way, when no one else is referencing the resources, they will be eligible for garbage collection.

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

回答by NinjaCross

As already told by other users, what you are trying to achieve is already made by the GC, and can be fine tuned using a WeakReference.

正如其他用户已经告诉过的那样,您要实现的目标已经由 GC 完成,并且可以使用WeakReference进行微调。

This imply that in managed environments like .NET, java, and so on, this is a non-problem.

这意味着在 .NET、java 等托管环境中,这不是问题。

Since the low-level framework architecture isolates you from the memory management, if you still need for that kind of functionality, I strongly suggest you to review your own code architecture, cause it would mean that you are doing some sort of bad-practise in memory management

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

回答by Eric Lippert

Couple things. First off, objects are not reference counted; reference counting schemes have the circular reference problem, whereby two objects refer to each other but are otherwise inaccessible, and thereby leak. .NET uses a mark-and-sweep approach which does not use ref counts.

夫妇的事情。首先,对象没有被引用计数;引用计数方案存在循环引用问题,即两个对象相互引用但无法访问,从而导致泄漏。.NET 使用不使用引用计数的标记和清除方法。

Second, though the suggestion to use a weak reference is not terrible, it's also not a slam dunk. You are building a cache for performance reasons. (I assume that your careful, empirical, realistic research into the performance characteristics of your application has convincingly demonstrated that a caching strategy is necessary in order to achieve acceptable performance; if that's not the case, then you are making these decisions prematurely.) Every cache has to have a POLICY about when it releases its resources, otherwise it's a memory leak.

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

How do you know that the GC policy and your policy are equivalent policies? The GC was not designed with your specificperformance needs in mind. That is, it was designed to release resources that really are garbage, not to achieve any particular performance goal you've got in mind. By delegating the decision to the GC, you give up your ability to tune your cache policy to your performance needs.

你怎么知道GC策略和你的策略是等效的策略?GC 的设计没有考虑到您的特定性能需求。也就是说,它旨在释放真正垃圾的资源,而不是实现您心中的任何特定性能目标。通过将决定委托给 GC,您就放弃了根据性能需求调整缓存策略的能力。