在涉及不变的对象某些情况下,将有可能对于许多不同的对象接触到存在其中具有相同的语义。 一个简单的例子是从文件中读取文本的多行成字符串。 从程序的角度来看,事实上,两行有相同的字符序列将是“巧合”,而是从程序员的角度来看,大量的重复的可预期的。 如果多串的实例是相同的,不断变化的那些不同的情况下,引用到引用单个实例将节省内存,也将促进他们之间的比较(如果两个字符串引用指向相同的字符串,就没有必要做一个character-逐个字符地比较,以确定它们是相同的)。
对于某些情况下,该系统提供的字符串实习设施可能是有用的。 它有,然而,一对夫妇的限制,例如:
- 一旦字符串被拘留,该拘留的副本将永远活着,是否有任何其他的引用是否存在于它
- 串实习设施仅仅处理字符串的工作,并且不与任何其他不变类型使用。
如果存在一个真正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等)被分配的连续负数。 其具有(或者被分配)下时间戳值的参数将随后被其它取代。
使用这种方法,如果许多对象实例进行相互反复比较,许多文献将被用为“老”的实例的引用取代。 根据不同的使用模式,这可能会导致大部分相同的对象实例被兼并,而无需使用任何类型的实习字典的。 施加这样的方法与嵌套的对象,但是,将需要“不可改变的”对象允许嵌套对象引用被突变,以指向推测其他-相同嵌套对象。 这应该是很好,如果“理应相同”的对象始终是,但如果没有可能会导致相当奇特的不当行为。