【发布时间】:2016-10-04 11:59:15
【问题描述】:
我在使用TObjectList<T> 类的Contains、Remove 或IndexOf 等方法时遇到问题,
当 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、IndexOf 和Remove 使用TMyObject 的Equals 过程并覆盖此过程的实现。因此,我在我的 TSocket 类中添加了 Equals 的以下实现:
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 不删除对象但应删除它。我预计这些方法会使用TSocket 的Equals 方法,但他们没有。阅读文档后,我发现TObjectList 的构造函数可以通过 IComparer 的实现来调用。因此我实现了一个TEqualityComparer<TSocket> 以使用我的Equals 方法。
不幸的是TObjectList的构造函数不支持IEqualityComparer接口,而是使用IComparer接口。
问题:
在 Delphi 中使用自定义类型时,如何使用 Contains、Remove 或 IndexOf 之类的方法?
在其他编程语言(如 Java 或 C#)中,Equals 用于比较列表类型中的对象。 Delphi 使用什么机制来比较对象?
更新 感谢您提供全面的反馈。我已经适当地更新了我的问题和代码。我详细说明了我在运行代码时的期望,并添加了更多代码以使我的意图更加清晰。 @DavidHeffernan:实施确实是错误的。我向 TInterfacedObject 添加了继承,以了解有关引用计数的更多信息。我从代码中删除了 TInterfacedObject。
【问题讨论】:
-
大问题是你混合了引用计数的接口和对象。你必须阻止它。这里代码的每一部分都是严重错误的。
Contains、Remove、IndexOf已经可以正常使用您的类型,但您使用的类型错误,因此您需要重新开始。 -
对不起,如果我的代码质量不好,我还在努力学习这门语言
-
我在代码 cmets 和 does not work 或 did not work 的文本中都看到了很多提及,但没有单独解释什么not work 特指。如果您不能清楚地解释您遇到的问题,您就不能指望我们帮助您解决它。 没有按预期工作只有在我们知道您预期以及它没有达到这些预期的原因时才有意义。
-
当说某事“不起作用”时,您应该说明“预期行为”以及“实际行为”是什么。在您的情况下,猜测(仍然是 猜测)您“期望
sockets.Contains(socket)返回 True”是合理的,但它“实际上返回 False”。 (作为旁注,声称sockets.Remove(socket)不起作用是毫无意义的,因为它甚至没有被执行。)最后,你的 MCVE 是不完整的,因为你没有证明你是如何将你的套接字添加到sockets首先。这将是任何错误的关键部分。 -
注意!
IndexOf返回从零开始的索引,因此 0 是列表中第一个条目的有效索引。
标签: delphi equals tobjectlist