【问题标题】:Delphi TDictionary : values are replace automatically when have the same keyDelphi TDictionary :当具有相同的键时,值会自动替换
【发布时间】:2014-10-18 13:06:05
【问题描述】:

我正在使用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. 

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

【问题讨论】:

  • 这里显示的代码似乎没有描述的错误。让它编译,看看你是否遗漏了重要的代码片段。
  • 请发布显示问题的真实代码,这将永远无法编译

标签: delphi tdictionary


【解决方案1】:

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

您正在创建对象,然后将它们添加到字符串列表中

TS.AddObject(...);

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

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

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

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

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


我确实想知道字符串列表是否是此处使用的正确类。使用TObjectDictionary&lt;string, TClass1&gt; 可能会更好。你可以这样创建它:

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

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

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

【讨论】:

  • 我支持使用 TDictionary。根据我的尝试,它比使用 TStringList 做同样的事情要快得多。
猜你喜欢
  • 2023-01-27
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 2022-08-12
相关资源
最近更新 更多