1

I declare this object

MyDict := TDictionary<TPair<int32, int64>, bool>.create([]);
MyDict.add(TPair<Int32, Int64>.create(2, 0), true);

why

MyDict.TryGetValue(TPair<int32, int64>.create(2, 0), result)

can not found the previous key I just added?

zeus
  • 12,173
  • 9
  • 63
  • 184
  • Maybe this question can help https://stackoverflow.com/questions/16920502/record-equality-in-generic-collections – Triber May 11 '20 at 14:07

1 Answers1

2

The problem is that the default equality comparer for TPair<TKey,TValue> tests naive binary equality for the record. In your case the record specialises as:

TPair<int32,int64> = record
  Key: int32;
  Value: int64;
end;

Because the record is aligned, there is padding. There are four bytes of padding between Key and Value. The values of this padding is then used by the default comparer.

If you could define your own type, instead of using TPair<TKey,TValue> then you could declare it packed. That will be fine for simple value types as you use here for TKey and TValue, but more complex non-value types then even that would fail.

The other approach is to define your own equality comparer, and pass it to the dictionary constructor. You can do this by calling TEqualityComparer<TPair<TKey,TValue>>.Contruct() passing an equality comparison function and a hasher function. See this question for an example: What is the canonical way to write a hasher function for TEqualityComparer.Construct?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490