delphi Использование записей в качестве ключа в TDictionary
Можете ли вы использовать запись в качестве значения ключа в 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.
1 ответ
Да, вы можете использовать записи в качестве ключей в 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;
Вместо использования записи в качестве ключа вы можете использовать строку, состоящую из сериализованной записи. Вы можете использовать что-то вроде https://github.com/hgourvest/superobject для сериализации.
Поскольку строки имеют встроенную семантику сравнения и хэш-коды, вам не нужно писать функции сравнения и хэш-коды.
Мой лучший подход - объединить хэш-код по умолчанию для базовых типов.
Например:
Value.App.GetHashCode + Value.ID.GetHashCode + Value.Nr.GetHashCode;