gpt4 book ai didi

delphi - 通用集合中的记录相等性

转载 作者:行者123 更新时间:2023-12-03 14:47:07 25 4
gpt4 key购买 nike

假设您有一 strip 有重载相等运算符的记录

TSomeRecord = record
Value : String;
class operator Equal(Left, Right : TSomeRecord) : Boolean;
end;

(实现比较字符串值)。如果根据重载运算符将两条相等的记录添加到列表中,我希望 Contains 方法在这两种情况下都返回 true。但实际上,通用列表似乎只是比较记录的内存内容,而不是应用重载的相等运算符。

var
List : TList <TSomeRecord>;
Record1,
Record2 : TSomeRecord;

begin
Record1.Value := 'ABC';
Record2.Value := 'ABC';
List.Add(Record1);

Assert(List.Contains(Record1));
Assert(List.Contains(Record2)); // <--- this is not true
end;

这是预期的行为吗?有什么解释吗?

最佳答案

假设您没有在构造函数中指定比较器 TList.Create你会得到TComparer<TSomeRecord>.Default作为你的比较者。这是一个使用 CompareMem 执行简单二进制比较的比较器.

这对于充满值类型且没有填充的记录来说很好。但否则,在实例化列表时,您将需要提供自己的比较函数。

如果你想看细节,记录的默认比较器是在 Generics.Defaults 中实现的。 。对于较大的记录,相等比较器是以下函数:

function Equals_Binary(Inst: PSimpleInstance; const Left, Right): Boolean;
begin
Result := CompareMem(@Left, @Right, Inst^.Size);
end;

对于较小的记录,有一个优化,您的比较器将是 4 字节比较器。看起来像这样:

function Equals_I4(Inst: Pointer; const Left, Right: Integer): Boolean;
begin
Result := Left = Right;
end;

这有点奇怪,但它会将记录的 4 个字节解释为 4 字节整数并执行整数相等比较。换句话说,与 CompareMem 相同,但效率更高。

您要使用的比较器可能如下所示:

TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := CompareStr(Left.Value, Right.Value);
end;
)

使用CompareText如果你想要不区分大小写,等等。我使用了有序比较函数,因为这就是 TList<T>想要。

默认记录比较是相等比较这一事实告诉您,尝试在不指定自己的比较器的情况下对记录列表进行排序将会产生意外结果。

鉴于默认比较器使用相等比较,这告诉您使用这样的比较器并非完全不合理:

TComparer<TSomeRecord>.Construct(
function const Left, Right: TSomeRecord): Integer
begin
Result := ord(not (Left = Right));
end;
)

这对于像 IndexOf 这样的无序操作来说很好。或Contains但显然对于排序、二分查找等根本没有用处。

关于delphi - 通用集合中的记录相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16920502/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com