如何使用TObjectList <t>的Contains,Remove或IndexOf等方法

时间:2016-06-04 13:46:55

标签: delphi equals tobjectlist

我在使用==类的ifContainsRemove等方法时遇到问题, 当T是以下示例代码中的IndexOf之类的自定义类型时。

我开始实施自定义TObjectList<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的{​​{1}}过程,并覆盖此过程的实施。因此,我将Remove的以下实现添加到我的TSocket类:

Equals

使用此代码TMyObject返回false但应该为true,Equals返回-1但应该为0而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 IndexOf方法。在阅读文档后,我发现Remove的构造函数可以通过IComparer的实现来调用。因此,我实施了Equals以使用我的TSocket方法。 不幸的是,TObjectList的构造函数不支持TEqualityComparer<TSocket>接口,而是使用Equals接口。

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

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

1 个答案:

答案 0 :(得分:7)

您的错误是您假设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(通常为-1),则返回低于0的值
  • 如果L大于R(通常为1)
  • ,则返回大于0的值
  • 两者的返回0都是等于。

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