Smalltalk 没有键或大小为1的值的WeakIdentityKeyDictionary?

Smalltalk 没有键或大小为1的值的WeakIdentityKeyDictionary?,smalltalk,pharo,Smalltalk,Pharo,在Pharo中尝试此脚本: dictionary := WeakIdentityKeyDictionary new. key := Object new. dictionary at: key put: 'hello'. dictionary size. " --> 1 " key := nil. 2 timesRepeat: [Smalltalk garbageCollect]. 现在字典应该是空的了。然而: dictionary keys isEmpty. " --> true

在Pharo中尝试此脚本:

dictionary := WeakIdentityKeyDictionary new.
key := Object new.
dictionary at: key put: 'hello'.
dictionary size. " --> 1 "
key := nil.
2 timesRepeat: [Smalltalk garbageCollect].
现在字典应该是空的了。然而:

dictionary keys isEmpty. " --> true"
dictionary values isEmpty. " --> true "
正如所料,但是

dictionary isEmpty. " --> false ??"
dictionary size. " --> 1 !! "

这似乎是故意的。如果您阅读了WeakKeyDictionary类(
WeakEntityKeyDictionary
的超类)的注释:

我是一本字典,钥匙扣得很紧。这有点危险,因为任何时候我的钥匙都会被拿走。客户端负责通过WeakArray注册我的实例,以便在丢失任何密钥时采取适当的操作由于密钥可能随时消失,我报告的大小可能大于迭代中遇到的密钥数。

(强调矿山)

字典的内部数组仍然具有关联
nil-->'hello'
,这就是为什么字典的
size
为1,但
WeakIdentityKeyDictionary
关联do:
检查
nil
键并避免对其求值(请参见最后一行):


Dictionary#associations
基于
associationsDo:
,因此
字典关联
也是空的。

是有意义的。因此,我想解决(潜在)不一致性的“解决方案”应该是
#size
#isEmpty
的客户首先调用
#finalizeevalues
…我不知道您的上下文,但另一种选择是使用另一个类对字典进行子类化或修饰,该类的
大小和其他每一条消息都取决于
关联。但这可能更难,而且CPU更密集。
associationsDo: aBlock 
    "Evaluate aBlock for each of the receiver's elements (key/value 
    associations)."

    super associationsDo: [:association | | key | 
        "Hold onto the key so it won't be collected while the block is evaluated."
        key := association key.
        key ifNotNil:[aBlock value: association]].