Delphi TDictionary:当具有相同的密钥时,值将自动替换

时间:2014-10-18 13:06:05

标签: delphi tdictionary

我正在使用delphi XE5。 这是我的代码的简历,下一代码可以工作,但我的代码中必须有一些东西可以破坏正常的行为:

unit Class1;
type
 TClass1 = class
  private 
    FDic:TDictionary<String,String>.Create;
  public
constructor create;
    procedure insertValue(key,value:String);
  end;

 implementation
 constructor TClass1.create;
 begin
   FDic:=TDictionary<String,String>.Create;
 end;
 procedure insertValue(key,value:String);
 begin
  if(FDic.ContainsKey(key))then
      FDic[key] := value
  else
  begin
    FDic.Add(key,value);
  end;
end.

现在是另一个单位:

 unit Class2;
 type
  uses Class2;
  TClass1 = class
   public
     class2 :TClass2;
     TS: TStringList;
     procedure DoSomething;
   end;

   implementation

   procedure TClass1.DoSomething;
   var 
   i: Integer;
    c,test: TClass1;
   begin

    c := TClass1.create;
        c.insertValue('height','.34cm');
    c.insertValue('width','22cm');
    c.insertValue('radio','2cm');
        TS.AddObject('square',c);
        c := TClass1.create;
        c.insertValue('height','.88cm');
    c.insertValue('width','11cm');
    c.insertValue('top','12cm');
        TS.AddObject('circle',c);

         test := TS.Objects[0] as TClass1;//test.FDic height should be .34cm but gets the value of the last object create, the same for width an common keys.

   //here when I look for the values of FDic test.FDic.Items['height'] the value is .88cm instead of .34cm, each time the values of any element of the Dictionary is replace with the previous of the last object created. And the memory address is the same. Why don't create a new memory address for any new element if it is a different object. 

这是我的代码的简历,我可以把我的所有代码都放得太大,但我想知道在哪里可以搜索来解决这个问题。我不是不容易,也许我不是唯一一个有问题的人,也许是在使用中的一些类,类变量,有一些东西导致该字典中的内存问题,但无法找到它。

1 个答案:

答案 0 :(得分:1)

确定问题有点困难,因为您发布了无法编译的代码。为了将来参考,请不要这样做。将代码减小到一个小尺寸是很好的,但是你应该把它变成一个小的控制台应用程序来编译和运行并演示错误。尽管如此,我认为我可以看到问题所在。

您正在创建对象,然后使用

将它们添加到字符串列表中
TS.AddObject(...);

但是你永远不会释放那些物品。我想,这是泄漏的根源。您可以通过将字符串列表的OwnsObjects属性设置为True来处理此问题。

  

指定字符串列表是否拥有它包含的对象。

     

OwnsObjects 属性指定字符串列表是否拥有   存储的对象与否。如果 OwnsObjects 属性设置为 True ,   那么 Destroy 析构函数将释放为其分配的内存   那些对象。

我认为这将解释泄漏。问题的另一部分是为什么索引0包含您添加的项目。考虑到问题中的代码,唯一的解释是您的字符串列表将Sorted属性设置为True

再一次,我有点直觉地推断这一点,但是如果你只发布了一个完整的编译和运行的程序,那么你的问题可以完全肯定地回答。


我想知道字符串列表是否是正确使用的类。也许你会TObjectDictionary<string, TClass1>更好。您可以像这样创建它:

dict := TObjectDictionary<string, TClass1>.Create([doOwnsValues]);

doOwnsValues的使用告诉字典,它假定您添加为值的对象的所有权,并在从字典中删除它们时,或者在字典被销毁时销毁它们。

另请注意,insertValue方法可以使用AddOrSetValue方法以更简单的方式实现。