【问题标题】:Is it possible to create a truely weak-keyed dictionary in C#?是否可以在 C# 中创建一个真正的弱键字典?
【发布时间】:2012-01-16 11:36:28
【问题描述】:

我正试图找出一个真正的 C# WeakKeyedDictionary<,> 的细节......但我遇到了困难。

我意识到这是一项不平凡的任务,但似乎无法声明 WeakKeyedKeyValuePair<,>(其中 GC 仅在键可访问时遵循值引用)使得它看起来不可能。

我看到了两个主要问题:

  1. 到目前为止,我看到的每个实现都不会在收集键后修剪值。想一想 - 使用这样的字典的主要原因之一是防止这些值被保留(不仅仅是键!),因为它们无法访问,但在这里它们被强引用指向。

    是的,从字典中添加/删除足够多,它们最终会被替换,但如果你不这样做呢?

  2. 如果没有假设的WeakKeyedKeyValuePair<,>(或另一种告诉 GC 仅在键可访问时标记值的方法),任何引用它的键的值都不会被收集。这是存储任意值时的问题。

问题 1 可以通过一种相当不理想/骇人听闻的方式解决:使用 GC 通知等待完整的 GC 完成,然后继续在另一个线程中修剪字典。这个我还可以。

但问题 2 让我很困惑。我意识到这很容易被“所以不要那样做”所反驳,但这让我想知道 - 这个问题甚至有可能解决吗?

【问题讨论】:

    标签: c# .net dictionary garbage-collection weak-references


    【解决方案1】:

    看看ConditionalWeakTable<TKey, TValue> Class

    使编译器能够将对象字段动态附加到托管对象。

    它本质上是一个字典,其中键和值都是WeakReference,只要键还存在,值就会保持活跃。

    注意!这个类不使用GetHashCodeEquals做相等比较,它使用ReferenceEquals

    【讨论】:

    • 真可惜,它的实现似乎依赖于内部 .NET 魔术“DependentHandle”。此外,它忽略了 .GetHashCode 和 .Equals,充其量使其成为不合标准的字典 :(。此外,在无法访问 DependentHandle 的情况下,问题现在已经转移到定义 WeakValuedDictionary。我想这可能是我们能得到的最接近的了..
    • @Mania DependentHandle 是ephemerons 的CLR 实现,没有GC 合作是不可能实现的。它应该像 GCHandle 一样公开。如果您不介意反射技巧,您可以将静态 CLR 方法转换为委托并实现您自己的 DependentHandle 和 WeakValuedDictionary。仔细研究 .NET 参考源(它是公开的),或者使用一些反编译器,因为它有棘手的竞争条件。
    • @Zarat:顺便说一句,作为框架类,我希望看到的一件事是InternTable&lt;T&gt;(以IEqualityComparer&lt;T&gt; 作为构造参数)。给定T 的实例,确定表是否已经包含一个比较相等的条目。如果是,请比较该实例;否则,将提供的实例存储在表中并返回它。如果实施得当,这样的表可以极大地提高嵌套不可变类型的性能,其中哈希码可以非常可靠地区分不相等的实例,但比较相等的实例代价高昂。
    • @supercat:认为我们在这里有点偏离主题 :) 如果您想进一步讨论,可以通过邮件或在我的博客上进行。 I posted my reflection trickery 重新实现 DependentHandle 和一个类似于 WeakReference 对 GCHandle 的新 Ephemeron 类。
    • 我一直很感兴趣地关注这个讨论。我建议您在其他地方继续讨论,并在您的发现中发布一个自我回答的问题。请在此处提供链接,以便我可以继续关注此主题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-01-27
    • 2010-09-20
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多