delphi – 将相同的对象添加到TObjectDictionary两次可以释放对象

看这个代码
dic:=TObjectDictionary<Integer,TObject>.Create([doOwnsValues]);
testObject:=TObject.Create;
dic.AddOrSetValue(1,testObject);
dic.AddOrSetValue(1,testObject);

代码

>创建拥有包含值的Dictionary
>添加一个
>使用相同的键再次添加相同的值

令人惊讶的是,第二次添加对象时,该对象被释放.

这是有意的行为吗?还是Delphi库中的错误

文档简单地说:“如果对象拥有,当条目从字典中删除时,键和/或值将被释放”.所以似乎有点奇怪的是释放一个我刚刚要求添加的对象!

有没有办法告诉TObjectDictionary不这样做?目前,每次添加一个值时,我必须首先检查该密钥值组合是否已经在“字典”中.

德尔福2010

[编辑:
阅读所有评论后:

我的结论(为什么值得)

这似乎是预期的行为
>没有办法修改这个行为
>不要使用TObjectDictionary(或任何其他类似的类)除了普通的“添加这些对象到容器之外的任何其他类似的类”,将它们放在那里,做一些东西,释放容器和你添加的所有对象的用法.如果你做的更复杂,最好自己管理对象.
>行为记录不良,如果您真的想知道发生了什么,您应该阅读该来源

[/编辑]

解决方法

TObjectDictionary< TKEY的,TValue>实际上只是一个TDictionary< TKey,TValue>它在KeyNotify和ValueNotify方法中有一些额外的代码
procedure TObjectDictionary<TKey,TValue>.ValueNotify(const Value: TValue; 
  Action: TCollectionNotification);
begin
  inherited;
  if (Action = cnRemoved) and (doOwnsValues in FOwnerships) then
    PObject(@Value)^.Free;
end;

这是IMO,一个相当简单的方法,但是在ValueNotify方法中,不可能知道这是什么键,所以它只是释放“旧”值(没有办法检查这个值是否设置为相同的键).

您可以编写自己的类(这不是微不足道的),源自TDictionary< K,V>或者根本不使用doOwnsValues.你也可以写一个简单的包装器,例如TValueOwningDictionary< K,V>其使用TDictionary< K,V>首当其冲的工作,但处理所有权问题本身.我想我会做后者.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...