4

このようなことをしたいのですが、ペアを割り当てることができないため、コンパイルできません。

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 などの他の言語では、参照はその言語の第一級市民です。値ではなく参照を列挙する反復子を簡単に作成できます。それが、問題を簡潔に解決するために必要なことです。残念ながら、言語は不足しています。

明らかなオプションの 1 つは、値型 (レコード) ではなく参照型 (クラス) の使用に切り替えることです。参照を反復するため、反復の問題を一気に解決できます。ただし、通常は正当な理由で値型を使用することを選択し、この切り替えを行うのを妨げる制約がある場合があります。

もう 1 つの可能性は、値へのポインターを提供する反復子を提供するコンテナーを作成することです。これは、レコードへの参照に最も近いものです。ただし、独自のコンテナーをロールする必要があります。

于 2013-03-01T22:49:25.687 に答える