2014-10-18 72 views
-2

我使用delphi XE5。 這我的代碼簡歷,接下來的代碼工作,但必須是破壞正常行爲的東西在我的代碼:德爾福TDictionary:值有相同的密鑰時自動替換

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. 

這是一份簡歷我的代碼,我可以把我所有的代碼,因爲太大,但我想知道我可以搜索以解決這個問題。我並不是不容易,也許我不是唯一一個有這個問題的人,也許是某些類的用法,類變量,有些東西會導致字典中的內存問題,但無法找到它。

+2

此處顯示的代碼似乎沒有描述的錯誤。讓它編譯並看看你是否錯過了一個重要的代碼片斷。 – mjn 2014-10-18 13:28:08

+0

請發佈顯示問題的實際代碼,這將永遠不會編譯 – 2014-10-18 18:35:05

回答

1

由於您發佈了無法編譯的代碼,因此難以確定問題。爲了將來的參考,請不要這樣做。把代碼縮減到一個小的尺寸是很好的,但是你應該把它變成一個小的控制檯應用程序,它編譯並運行並演示錯誤。儘管如此,我認爲我可以看到問題出在哪裏。

你正在創建對象,然後將它們與

TS.AddObject(...); 

添加到一個字符串列表但你從來沒有免費的對象。我想這是泄漏的根源。您可以通過將字符串列表的OwnsObjects屬性設置爲True來處理此問題。

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

OwnsObjects屬性指定字符串列表是否擁有 存儲的對象。如果OwnsObjects屬性設置爲, 那麼破壞析構函數將釋放分配給 這些對象的內存。

我想這將解釋泄漏。你的問題的另一部分是爲什麼索引0包含你第二次添加的項目。考慮到問題中的代碼,唯一的解釋是您的字符串列表的Sorted屬性設置爲True

再一次,我用一點直覺來推斷這一點,但如果你只發布了一個完整的程序,編譯和運行,那麼你的問題可能已完全確定地回答。


我不知道字符串列表是否是在這裏使用的正確的類。也許你會更好用TObjectDictionary<string, TClass1>。你會喜歡這個創建它:

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

採用doOwnsValues告訴它是以假設你添加爲值,並摧毀他們的對象的所有權時,他們從字典中刪除,或當字典詞典被銷燬。

還請注意,您的insertValue方法可以使用AddOrSetValue方法以更簡單的方式實現。

+0

我贊同使用TDictionary。基於我的嘗試,它比使用TStringList的速度要快很多。 – 2014-10-18 13:26:55