Delphi TObjectDictionary having a class instance key

I have the following class:

TTest = class
private
  FId: Integer;
  FSecField: Integer;
  FThirdField: Integer;
public
  constructor Create(AId, ASecField, AThirdField: Integer);
  // ..... 
end;

Then I create TObjectDictionaryas follows:

procedure TMainForm.btnTestClick(Sender: TObject);
var
  TestDict: TObjectDictionary<TTest, string>;
  Instance: TTest;
begin
  TestDict := TObjectDictionary<TTest, string>.Create([doOwnsKeys]);

  try
    TestDict.Add(TTest.Create(1, 1, 1), '');

    if TestDict.ContainsKey(TTest.Create(1, 1, 1)) then
      ShowMessage('Match found')
    else
      ShowMessage('Match not found');

    Instance := TTest.Create(1, 1, 1);
    TestDict.Add(Instance, 'str');

    if TestDict.ContainsKey(Instance) then
      ShowMessage('Match found')
    else
      ShowMessage('Match not found');
  finally
    TestDict.Free;
  end;
end;

The result is: "Match not found", "Match found". What should I do to compare the field values ​​of each key, but not their addresses?

+4
source share
1 answer

The default comparison tool for the instance reference variable compares the link, not the object. This way you get the object identifier, not the value identifier.

Thus, you need to provide your own comparison mapper if you want to enter a value identifier.

TestDict := TObjectDictionary<TTest, string>.Create(
  [doOwnsKeys], 
  TEqualityComparer<TTest>.Construct(EqualityComparison, Hasher)
);

EqualityComparison, Hasher - . :

EqualityComparison := 
  function(const Left, Right: TTest): Boolean
  begin
    Result := (Left.FId = Right.FId)
      and (Left.FSecField = Right.FSecField)
      and (Left.FThirdField = Right.FThirdField);
  end;

Hasher := 
  function(const Value: TTest): Integer
  begin
    Result := BobJenkinsHash(Value.FId, SizeOf(Value.FId), 0);
    Result := BobJenkinsHash(Value.FSecField, SizeOf(Value.FSecField), Result);
    Result := BobJenkinsHash(Value.FThirdField, SizeOf(Value.FThirdField), Result);
  end;
+3

Source: https://habr.com/ru/post/1624077/


All Articles