ten reprodukuje problem:TDictionary Hashing jest podzielony na zapisy ciągów
program Project1;
{$APPTYPE CONSOLE}
uses
Generics.Collections;
type
TStringRec = record
s1 : string;
s2 : string;
end;
TGetHash<TKey,TValue> = class(TEnumerable<TPair<TKey,TValue>>)
public
type
TItem = record
HashCode: Integer;
Key: TKey;
Value: TValue;
end;
TItemArray = array of TItem;
public
FItems: TItemArray;
end;
var
LCrossRef : TDictionary<TStringRec, integer>;
LRec : TStringRec;
i : integer;
begin
LCrossRef := TDictionary<TStringRec, integer>.Create();
LRec.s1 := 'test1';
LRec.s2 := 'test2';
LCrossRef.Add(LRec, 1);
LRec.s1 := 'test1';
LRec.s2 := 'test2';
if LCrossRef.TryGetValue(LRec, i) then begin
writeln('ok');
end else begin
LCrossRef.Add(LRec, 1);
for i := Low(TGetHash<TStringRec, integer>
(LCrossRef).FItems)
to High(TGetHash<TStringRec, integer>
(LCrossRef).FItems) do
WriteLn(TGetHash<TStringRec, integer>(LCrossRef).FItems[i].HashCode);
WriteLn('not ok');
end;
ReadLn;
end.
Słownik nie odzyskać pozycję i generuje inny HashCode
dla rekordów zawierających identyczne ciągi.
ta jest częściowo zauważyć w QC-#122791 ale obejście używać suchy rekordy nie działa dla zapisów ciągów (przynajmniej powyższy przykład nie również kiedy TStringRec
jest zadeklarowana jako packed record
).
Czy istnieje rozsądne obejście tego problemu?
Moja obecna strategia polega na łączeniu łańcuchów, które w innym przypadku byłyby zapisane w nagraniu i użycia zamiast tego wartości TDictionary<string, TValue>
, ale jest to naturalnie niesatysfakcjonujące.
Co powiesz na używanie TObjectDictionary z niestandardowym narzędziem IEqualityComparer, które implementuje GetHashCode dla określonego typu? –
@VilleKrumlinde Nie masz na myśli 'TObjectDictionary'. Nie ma tu własności obiektu. –
Wdrażanie 'IEqualityComparer' jest zdecydowanie drogą do zrobienia. –