简体   繁体   English

delphi 在 TDictionary 中使用记录作为键

[英]delphi Using records as key in TDictionary

Can you use a record as a Key value in TDictionary? TDictionary 中可以使用记录作为 Key 值吗? I want to find objects based on combination of string, integer and integer.我想根据字符串、整数和整数的组合来查找对象。

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;

This returns object 2.这将返回对象 2。

Yes, you can use records as keys in a TDictionary but you should provide your own IEqualityComparer when creating the dictionary because the default one for records just does a dumb binary compare of the record.是的,您可以将记录用作 TDictionary 中的键,但您应该在创建字典时提供自己的 IEqualityComparer,因为记录的默认值只是对记录进行愚蠢的二进制比较。 This fails for a record containing a string because it just compares the pointer of that string which may be different even if the string contains the same value.这对于包含字符串的记录失败,因为它只是比较该字符串的指针,即使该字符串包含相同的值,该指针也可能不同。

Such a comparer would look like this:这样的比较器看起来像这样:

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;

Instead of using the record as a key, you could use a string consisting of the serialized record.您可以使用由序列化记录组成的字符串,而不是使用记录作为键。 You could use something like https://github.com/hgourvest/superobject to do the serialization.您可以使用类似https://github.com/hgourvest/superobject 的东西来进行序列化。

Since strings have built-in comparison semantics and hashcodes, you don't need to write comparison and hashcode functions.由于字符串具有内置的比较语义和哈希码,因此您无需编写比较和哈希码函数。

My best approach should be to joint the default hash code of the base types.我最好的方法应该是联合基本类型的默认哈希码。

For instance:例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM