是否可以将 ConditionalWeakTable 与元组键(或由多个引用组成的键)一起使用?

问题描述 投票:0回答:2

我是

ConditionalWeakTable
的忠实粉丝。 真的非常棒。 它本质上允许您将一个引用关联/附加/配对到另一个引用,同时保持线程安全。

它为我解答了很多问题。 不幸的是,我似乎一直遇到一个问题,并且无法找到一个好的答案。

假设我有一个方法(由下面的测试方法表示),其中我使用

ConditionalWeakTable
,但我不需要对键使用单个引用,而是需要组合两个项目并将其作为键。 下面通过
Key
对象显示了这一点(这只是一个扩展的
Tuple
,用于演示目的和简洁性):

[Fact]
public void TupleKey()
{
    var first = new object();
    var table = new ConditionalWeakTable<Key, object>();
    var context = table.GetValue( new Key( first, new object() ), key => new object() );

    // .. table has one entry here.

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Debugger.Break(); // Table is empty here.

}

class Key : Tuple<object, object>
{
    public Key( object item1, object item2 ) : base( item1, item2 ) {}
}

当调用

Debugger.Break
时,
ConditionalWeakTable
为空,即使测试方法中存在对
Key
部分之一的活动引用。 这是有道理的,因为在测试中找不到对
Key
的引用。

但是,由于存在对

Key
对象的某一部分的一个活动引用,因此我希望
ConditionalWeakTable
中的条目也保持活动状态,并保持活动状态,直到声明其所有子级/内部引用。

(在考虑这个和可能的解决方案时,如果有一个 WeakHashSet 可以以某种方式用作

Dictionary<>
的钥匙,那就太棒了
,但从一些搜索来看,似乎没有 
WeakHashSet
存在于.NET 中。)

希望这能概述我的困境。 我基本上想使用

ConditionalWeakTable

 (或某些等效项)来存储关联的值(作为键/值条目),但我不想使用一个(弱)引用作为条目的键,我想使用两个(或更多)。

我希望实现的目标是否可能(即无需编写大量自定义代码)?

c# .net memory-management weak-references
2个回答
2
投票
这个问题与

这个问题相关,我终于找到了一个解决这个问题的答案,那个答案很好。 您可以阅读答案了解更多详情。

关于这个问题。 这归结为更精致/聪明/智能地使用“钥匙”来使用

ConditionalWeakTable

。  就我而言,我正在努力解决密钥的三个部分(实例、方法和参数)。  我设法使用 
Delegate
(基本上是实例和方法的参考元组)组合前两个,然后将其与使用 
Dictionary<object[], object>
StructuralEqualityComparer
配对。 哇啦。 问题解决了。


0
投票
经过一些粗略的测试,我很幸运地进行了嵌套

ConditionalWeakTable

。例如,对于接受三个参数并根据所有三个键的引用进行记忆的 F# 记忆函数,这似乎有效:

module Memoize = /// Memoizes the specified function using reference equality on the input arguments. /// The result is cached for the lifetime of the key. /// /// Don't call with additional arguments as ad-hoc tuples or records, /// since these will never be reference equal. let refEq3<'k1, 'k2, 'k3, 'v when 'k1: not struct and 'k2: not struct and 'k3: not struct and 'v: not struct> (f: 'k1 -> 'k2 -> 'k3 -> 'v) = let cache = ConditionalWeakTable<'k1, ConditionalWeakTable<'k2, ConditionalWeakTable<'k3, 'v>>>() fun k1 k2 k3 -> let inner1 = cache.GetOrCreateValue(k1) let inner2 = inner1.GetOrCreateValue(k2) match inner2.TryGetValue(k3) with | true, v -> v | false, _ -> let v = f k1 k2 k3 inner2.Add(k3, v) v
    
© www.soinside.com 2019 - 2024. All rights reserved.