2013-03-01 52 views
3

我想要做這樣的事情,但它不會編譯,因爲Pair不能分配給。有沒有一種簡潔的方式來更新記錄的TDictionary中的所有值?

var 
    MyDictionary: TDictionary<TGuid, TCustomRecord>; 
    Pair: TPair<TGuid, TCustomRecord>; 
begin 
    // ... create and populate my dictionary ... 

    foreach Pair in MyDictionary do 
    begin 
    PairRef.Value.MyField := PairRef.Value.MyField + 1; 
    end; 
end 

只是要清楚,我知道如何用更多的代碼來實現這一點,我在尋找簡潔易讀的東西。

+0

您可以使用TDictionary 。值 – 2013-03-01 21:59:39

+0

您希望能夠修改for循環中的鍵或值嗎?如果你只是想操作數值 – Petesh 2013-03-01 22:00:24

+0

@SirRufo,Values是隻讀啓動器 – 2013-03-01 22:04:06

回答

2

TDictionary上沒有迭代器,它返回對值的引用。所有的迭代器都提供了值,這意味着你所要求的是當前設計所不可能的。

在其他語言中,例如我知道的C++和D,引用是該語言中的第一類公民。您可以輕鬆地編寫枚舉引用而不是值的迭代器。這就是你需要簡潔地解決你的問題。不幸的是,這種語言缺乏。

一個明顯的選擇是切換到使用引用類型(類)而不是值類型(記錄)。這將解決中風中的迭代問題,因爲它將迭代引用。然而,人們通常選擇使用價值類型是有原因的,而且您可能會遇到阻礙您進行此類轉換的限制。

另一種可能性是編寫一個容器,該容器提供了提供指向值的指針的迭代器。這與您可以獲得對記錄的引用盡可能接近。但是你將不得不推出自己的容器。

+0

該死的,這不是我希望的答案。 – 2013-03-01 23:45:55

+0

這將是醜陋的,但我不知道你是否可以通過製作指向記錄的TDictionary來解決這個問題。 (Gross,我知道) – 2013-03-02 12:47:09

+0

@Warren但誰擁有這些記錄?你必須爲他們有一個單獨的容器。 – 2013-03-03 08:29:16

8

下面是一個簡單的程序,它顯示了使用記錄和對象與TDictionary不同的處理。

program Project1; 

{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, System.Generics.Collections; 

type 
    TMyRecord = record 
    Field : Integer; 
    end; 

    TMyObject = class 
    Field : Integer; 
    end; 

procedure UseObjectDict; 
var 
    LDict : TDictionary<TGUID, TMyObject>; 
    LValue : TMyObject; 
begin 
    write('TMyObject: '); 

    LDict := TObjectDictionary<TGUID, TMyObject>.Create([doOwnsValues]); 
    try 

    // populate 
    while LDict.Count < 10 do 
    begin 
     LDict.Add(TGuid.NewGuid, TMyObject.Create); 
    end; 

    // update 
    for LValue in LDict.Values do 
     begin 
     LValue.Field := LValue.Field + 1; 
     end; 

    // output 
    for LValue in LDict.Values do 
     begin 
     write(LValue.Field, ', '); 
     end; 
    Writeln; 

    finally 
    LDict.Free; 
    end; 
end; 

procedure UseRecordDict; 
var 
    LDict : TDictionary<TGUID, TMyRecord>; 
    LKey : TGUID; 
    LValue : TMyRecord; 
begin 
    write('TMyRecord: '); 
    LDict := TDictionary<TGUID, TMyRecord>.Create; 
    try 

    // populate 
    while LDict.Count < 10 do 
     begin 
     LValue.Field := 0; 
     LDict.Add(TGuid.NewGuid, LValue); 
     end; 

    // update 
    for LKey in LDict.Keys do 
     begin 
     LValue.Field := LDict[LKey].Field + 1; 
     LDict.AddOrSetValue(LKey, LValue); 
     end; 

    // output 
    for LValue in LDict.Values do 
     begin 
     write(LValue.Field, ', '); 
     end; 
    Writeln; 

    finally 
    LDict.Free; 
    end; 
end; 

begin 
    ReportMemoryLeaksOnShutdown := True; 
    try 

    UseObjectDict; 
    UseRecordDict; 

    except 
    on E : Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 

    ReadLn; 

end. 
+1

+1可怕的是,我們需要跳過這樣的箍... – 2013-03-02 09:26:23

相關問題