我正在寻找一种在 C# 中执行此操作的方法:

  • 一个 Asker 对象将向 Giver 对象询问 Resource 对象。
  • 当被问到时,Giver 将在它的字典中搜索现有的匹配资源。如果找到,则返回资源的引用;否则,它将从数据库数据创建一个新的 Resource,将该引用保存在 Dictionary 中,最后返回该引用。
  • Asker 可能会多次请求相同的资源,在这种情况下,Giver 将从字典中返回相同的资源相同的次数。
  • 询问者可能在任何时候都没有使用给定的资源,在这种情况下,它不会对资源做任何进一步的事情。
  • 问题:Giver 如何检测任何不再使用的资源并将其从字典中删除?最好,Giver 应该在没有 Asker 帮助的情况下执行此操作。

  • 这可能吗?我似乎无法解决这个问题。

    编辑:
    感谢大家的精彩回复。尤其是弱引用。我不知道他们在那里。但是我有两个主要目标,我可以更清楚地说明它们。
  • Giver 不应依赖 Asker 来获得通知。
  • 当给定的资源在使用中时,所有的引用都必须指向同一个资源,这样对资源的修改就会反射(reflect)在所有使用同一个资源的地方。

  • 编辑:
    [删除了错误的代码块]

    最佳答案

    首先,您所谈论的是 IDisposable 接口(interface)背后的基本思想:一种确定性的资源释放方式。虽然它的主要用途是与需要显式释放的非托管资源交互(或与执行此操作的对象交互),但它的用法不限于此。

    不幸的是,它没有满足您的最后一个要求:由于它是确定性的,因此必须由某人调用。这个人必须是提问者。

    我能想到的唯一解决方案是在 WeakReference 对象中使用 Giver 类。这允许您维护对实例的引用,而不会阻止它被垃圾收集(收集后,您的引用变为 null )。

    不幸的是,这不是确定性的。在实际收集对象后,您的引用将变为 null (并且 IsAlive 将成为 false ),这不能保证在任何特定时间(或在您的应用程序的生命周期内)发生。

    考虑到这些警告,您可以像这样:

    public class Giver
    {
        private Dictionary<string, WeakReference> cache =
            new Dictionary<string, WeakReference>();
    
        public object GetResource(string resourceName)
        {
            WeakReference output;
            object returnValue = null;
    
            if(cache.TryGetValue(resourceName, out output))
            {
                if(output.IsAlive) returnValue = output.Target;
    
                if(returnValue == null) cache.Remove(resourceName);
            }
    
            if(returnValue == null)
            {
                returnValue = ...; // get the actual resource
    
                cache.Add(resourceName, new WeakReference(returnValue));
            }
    
            return returnValue;
        }
    }
    

    关于C# "shared pointer"用于替代内存管理?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4864686/

    10-10 21:55