-->

身体虚弱的实习集合(不可变对象)(Any weak interning collections (f

2019-06-25 06:25发布

在涉及不变的对象某些情况下,将有可能对于许多不同的对象接触到存在其中具有相同的语义。 一个简单的例子是从文件中读取文本的多行成字符串。 从程序的角度来看,事实上,两行有相同的字符序列将是“巧合”,而是从程序员的角度来看,大量的重复的可预期的。 如果多串的实例是相同的,不断变化的那些不同的情况下,引用到引用单个实例将节省内存,也将促进他们之间的比较(如果两个字符串引用指向相同的字符串,就没有必要做一个character-逐个字符地比较,以确定它们是相同的)。

对于某些情况下,该系统提供的字符串实习设施可能是有用的。 它有,然而,一对夫妇的限制,例如:

  1. 一旦字符串被拘留,该拘留的副本将永远活着,是否有任何其他的引用是否存在于它
  2. 串实习设施仅仅处理字符串的工作,并且不与任何其他不变类型使用。

如果存在一个真正WeakDictionary<ImmutableClassType, ImmutableClassType>对于每个元件,所述键和值将是相同的),代码可以这样做:

if (theDict.TryGetValue(myString, ref internedString))
  myString = internedString;
else
  theDict[myString] = myString;

不幸的是,我不知道任何内置的WeakDictionary<keyType, valType>在.NET类。 此外,它似乎浪费生成每个项目的键和值,弱引用时都引用总是指向同样的事情。

我读过一些关于ConditionalWeakTable ,和这听起来像一个有趣的课,但我不认为这将是可用在这里,因为我们的目标是能够采取一个实例,并找到另一个独立的实例,它在语义上等效。

对于其中一个类的实例将具有良好限定的寿命的情况下,也可能是合理使用常规Dictionary合并相同的实例。 在许多情况下,但是,它可能很难知道什么时候这样的Dictionary应该被抛弃或其中的物品清理出来。 一个WeakReference基础的实习集合会避免这样的问题。 难道这样的事情存在,或者可以将它很容易实现?

附录作为svick指出,一个Dictionary<WeakReference, WeakReference>将在一定程度上有问题的,因为是定义一个没有实际办法IEqualityComparer这将有一个活WeakReference返回GetHashCode其目标的价值,并有一个死一个继续返回值。 人们可以定义哪些将包含一个整数目标哈希码值(在构造函数中设置),以及其自己的一个结构GetHashCode都将返回一个整数。 略有改善可能是使用一个ConditionalWeakTable到的目标链路WeakReference到可以用来排队表中的项目要删除的终结对象。

我不知道急切地清洗一下适当的平衡是试图之间出了字典,对采取一个较为被动的方法(如执行添加项目时,如果有一直以来的最后一次扫描至少一个GC扫描和数字项目添加自上次扫描超过活下来)的项目数。 通过在字典中的一切席卷不会是免费的,但ConditionalWeakTable可能不会是免费的要么。

PPS另一个想法我在想的,但我想它可能不会像弱实习的做法是有用的,是有一个逻辑上不可变型保持一个可变的“时间戳”值,并且具有接受比较方法其论据ref 。 如果发现两个不同的实例是相等的,它们的时间戳值将被检查。 如果两个零,他们会从全球的计数器(-1,-2,-3等)被分配的连续负数。 其具有(或者被分配)下时间戳值的参数将随后被其它取代。

使用这种方法,如果许多对象实例进行相互反复比较,许多文献将被用为“老”的实例的引用取代。 根据不同的使用模式,这可能会导致大部分相同的对象实例被兼并,而无需使用任何类型的实习字典的。 施加这样的方法与嵌套的对象,但是,将需要“不可改变的”对象允许嵌套对象引用被突变,以指向推测其他-相同嵌套对象。 这应该是很好,如果“理应相同”的对象始终是,但如果没有可能会导致相当奇特的不当行为。

Answer 1:

你可以创建像Dictionary<WeakReference, WeakReference>使用自定义相等比较器和修剪那些不再活在适当的时间。 有一个问题是,如何去除死WeakRefrence从字典,因为你无法通过引用相等(记住,你必须使用自定义相等比较器)或索引中删除。 可能的解决方案是创建一个从继承的类WeakReference和具有即使引用是死对头的散列码。 或者你可以在自定义其包装struct

但正如你所说,它好像每个参考文献是从字典中删除它死了之后马上就好了。 我认为,要做到这一点的唯一方法就是以某种方式使用终结。 但是,如果你不想(或不能)修改词典中的类型,这将变得相当复杂。

其基本思想是有,你会弱引用相同的字典以上(有关如何删除的项目仍然适用的注意事项),但你也使用了终结附加辅助对象的每个项目在字典ConditionalWeakTable 。 而在这终结,你会从字典中删除该项目。 因为怎样的ConditionalWeakTable作品,如果在字典中的一个项获得GCed,附加的对象也不能免俗,这意味着它的终结将被调用,因此该项目将从字典中删除



文章来源: Any weak interning collections (for immutable objects)