14

TDictionary でキー値としてレコードを使用できますか? 文字列、整数、整数の組み合わせに基づいてオブジェクトを検索したい。

TUserParKey=record
  App:string;
  ID:integer;
  Nr:integer;
end;

...

var
  tmpKey:TUserParKey;
  tmpObject:TObject;
begin
  tmpObject:= TTObject.Create(1); 
  tmpKey.App:='1';
  tmpKey.ID :=1;
  tmpKey.Nr :=1;

  DTUserPars.Add(tmpKey,tmpObject)

...

var
  tmpKey:TUserParKey;
begin
  tmpKey.App:='1';
  tmpKey.ID :=1;
  tmpKey.Nr :=1;

  if not DTUserPars.TryGetValue(tmpKey,Result) then begin
    result := TTObject.Create(2); 
  end;

これにより、オブジェクト 2 が返されます。

4

3 に答える 3

21

はい、レコードを TDictionary のキーとして使用できますが、辞書を作成するときに独自の IEqualityComparer を提供する必要があります。これは、文字列に同じ値が含まれていても異なる可能性がある文字列のポインターを比較するだけなので、文字列を含むレコードでは失敗します。

このような比較子は次のようになります。

type
  TUserParKeyComparer = class(TEqualityComparer<TUserParKey>)
    function Equals(const Left, Right: TUserParKey): Boolean; override;
    function GetHashCode(const Value: TUserParKey): Integer; override;
  end;

function TUserParKeyComparer.Equals(const Left, Right: TUserParKey): Boolean;
begin
  Result := (Left.App = Right.App) and (Left.ID = Right.ID) and (Left.Nr = Right.Nr);
end;

function TUserParKeyComparer.GetHashCode(const Value: TUserParKey): Integer;
begin
  Result := BobJenkinsHash(PChar(Value.App)^, Length(Value.App) * SizeOf(Char), 0);
  Result := BobJenkinsHash(Value.ID, SizeOf(Integer), Result);
  Result := BobJenkinsHash(Value.Nr, SizeOf(Integer), Result);
end;
于 2015-01-07T13:07:30.493 に答える