gpt4 book ai didi

delphi - 如何使用 TObjectList 的 Contains、Remove 或 IndexOf 等方法

转载 作者:行者123 更新时间:2023-12-02 00:04:46 29 4
gpt4 key购买 nike

我在使用 Contains 等方法时遇到问题, RemoveIndexOfTObjectList<T>类(class),当 T 是自定义类型时,如 TSocket在下面的示例代码中。

我首先实现自定义 TSocket类型并尝试在类型 TObjectList<TSocket> 的列表中使用它像这样:

list := nil;
socket := nil;
try
list := TObjectList<TSocket>.Create();
socket := TSocket.Create(TIpAddress.Parse('127.0.0.1'),6857);

// add new socket object with equal values to list
list.Add(TSocket.Create(TIpAddress.Parse('127.0.0.1'),6857));

// should return true but returns false
if list.Contains(socket) then
WriteLn('socket contained in list')
else
WriteLn('socket not contained in list');

// should return number 0 but returns -1
if list.IndexOf(socket) = 0 then
WriteLn('socket contained in list')
else
WriteLn('socket not contained in list');

// should remove item from list but items doesn't get removed
list.Remove(socket);

finally
list.Free();
socket.Free();

我预计Contains , IndexOfRemove利用Equals TMyObject的程序并重写该程序的实现。因此我添加了以下 Equals 的实现到我的 TSocket 类:

type
TSocket = class
strict private
_ipAddress: TIpAddress;
_port: integer;
public
constructor Create(ipAddress: TIpAddress; port: integer);
function GetIpAddress: TIpAddress;
function GetPort: integer;
property IpAddress: TIpAddress read GetIpAddress;
property Port: integer read GetPort;
function Equals(other: TObject): boolean; overload; override;
destructor Destroy; override;
end;

implementation

constructor TSocket.Create(ipAddress: TIpAddress; port: integer);
begin
inherited Create();
_ipAddress := ipAddress;
_port := port;
end;

function TSocket.Equals(other: TObject): boolean;
var
otherSocket: TSocket;
begin
if not (other is TSocket) then exit(false);
otherSocket := other as TSocket;
result:= (_ipAddress.Equals(otherSocket.IpAddress)) and (_port = otherSocket.Port)
end;

function TSocket.GetIpAddress: TIpAddress;
begin
result := _ipAddress;
end;

function TSocket.GetPort: integer;
begin
result := _port;
end;

destructor TSocket.Destroy;
begin
_ipAddress.Free();
inherited Destroy();
end;

使用此代码Contains返回 false 但应该为 true,IndexOf返回 -1 但应该是 0 和 Remove不删除该对象,但应该删除它。我预计这些方法将使用 Equals方法TSocket但他们没有。阅读文档后我发现 TObjectList 的构造函数可以通过 IComparer 的实现来调用。因此我实现了 TEqualityComparer<TSocket>为了使用我的Equals方法。不幸的是 TObjectList 的构造函数不支持IEqualityComparer接口(interface),而是使用 IComparer界面。

问题:如何使用 Contains 等方法, RemoveIndexOfTObjectList<T>在 Delphi 中使用自定义类型时?在其他编程语言(如 Java 或 C#)中 Equals用于比较列表类型中的对象。 Delphi使用什么机制来比较对象?

更新感谢您的全面反馈。我已经适当更新了我的问题和代码。我详细说明了运行代码时我的期望,并添加了更多代码以使我的意图更加清晰。@DavidHeffernan:实现确实是错误的。我向 TInterfacedObject 添加了继承,以便了解有关引用计数的更多信息。我从代码中删除了 TInterfacedObject。

最佳答案

你的错误是你假设 TObjectList<T>使用 Equals函数来测试相等性。

默认情况下,TObjectList<T> ,或更准确地说TList<T> ,使用 TComparer<T>.Default 返回的比较器。以TObjectList<TSocket>为例,默认比较器比较指针本身。由于您创建了 2 个不同的对象,因此指针不同。您得到的结果就是预期的结果。

如果您想覆盖该默认行为,您需要提供自己的比较器。这样做的方法是将其传递给构造函数,如下所示:

TObjectList<TSocket>.Create(TComparer<TSocket>.Construct(
function (const L, R : TSocket) : Integer
begin
//Compare here.
end)
);

你的函数应该:

  • 如果 L 小于 R,则返回小于 0 的值。(通常为 -1)
  • 如果 L 大于 R,则返回大于 0 的值。(通常为 1)
  • 返回 0 两者相等。

如果出于某种原因,您只想检查是否相等,从技术上讲,您可以这样做,并在不相等时返回 -1 或 1,而无需进一步比较。也就是说,只要您不打算对列表进行排序或通过它进行 BinarySearch。

关于delphi - 如何使用 TObjectList<T> 的 Contains、Remove 或 IndexOf 等方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37630970/

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