看这个代码:
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>首当其冲的工作,但处理所有权问题本身.我想我会做后者.