4

我想做这样的事情,但它不会编译,因为无法分配 Pair 。

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

为了清楚起见,我知道如何使用更多代码来完成此任务,我正在寻找简洁易读的东西。

4

2 回答 2

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.
于 2013-03-01T22:40:59.733 回答
1

没有TDictionary返回对值的引用的迭代器。所有迭代器都提供值,这意味着您所要求的在当前设计中是不可能的。

在其他语言中,例如我所知道的 C++ 和 D,引用是该语言中的一等公民。您可以轻松编写枚举引用而不是值的迭代器。这就是你需要简洁地解决你的问题。可惜语言不通。

一个明显的选择是切换到使用引用类型(类)而不是值类型(记录)。这将一次性解决迭代问题,因为将迭代引用。但是,人们通常选择使用值类型是有充分理由的,并且您可能会遇到一些限制,阻止您进行此切换。

另一种可能性是编写一个提供迭代器的容器,该迭代器提供指向值的指针。这是尽可能接近对记录的引用。但是您必须滚动自己的容器。

于 2013-03-01T22:49:25.687 回答