delphi使用记录作为TDictionary中的键

时间:2015-01-07 13:04:07

标签: delphi generics collections tdictionary

你可以在TDictionary中使用记录作为Key值吗?我想基于字符串,整数和整数的组合找到对象。

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.

3 个答案:

答案 0 :(得分:19)

是的,您可以将记录用作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;

答案 1 :(得分:0)

您可以使用由序列化记录组成的字符串来代替将记录用作键。您可以使用类似https://github.com/hgourvest/superobject的方式进行序列化。

由于字符串具有内置的比较语义和哈希码,因此您无需编写比较和哈希码函数。

答案 2 :(得分:-1)

我最好的方法应该是合并基本类型的默认哈希码。

例如:

Value.App.GetHashCode + Value.ID.GetHashCode + Value.Nr.GetHashCode;