delphi 如何正确使用类函数对TStringList进行CustomSort?

lvmkulzt  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(111)

在 Delphi 中,我创建了一个类似这样的小类:

TFilesSorter = class
public
  constructor Create(ExtOrderList: TStrings);
  function SoryByExt(List: TStringList; Index1, Index2: Integer): Integer;
private
  ExtOrder: TStrings;
end;

字符串
我创建了一个类,因为SoryByExt函数需要一个排序中使用的扩展(ExtOrder)的有序列表。
当我尝试在CustomSort中使用我的类函数时,像这样:

FilesSorter := TFilesSorter.Create(ExtensionsList);
try
  SomeTStringList.CustomSort(FilesSorter.SoryByExt);
finally
  FilesSorter.Free;
end;


我得到一个错误:
E2009不兼容的类型:“常规过程和方法指针”
现在我明白为什么了(它只适用于非类函数),但是我想知道当你需要另一个变量(我在排序过程中使用的扩展的有序列表)而不使用全局变量时,如何使用CustomSort?我想分离责任,而不是共享变量。
什么是正确的方法来做到这一点(我使用 Delphi 11)?

9cbw7uwe

9cbw7uwe1#

TStringList.CustomSort()不支持其排序例程的非静态类方法。因此,当使用 * 标准 * TStringList时,如果您需要从排序例程内部访问外部变量,则它必须是全局变量。或者,由于排序例程确实可以访问正在排序的TStringList,你可以在TStringList.Objects属性的一个条目中存储一个指向外部变量的指针(如果你不使用它来做其他事情的话)。
否则,另一种选择是从TStringList派生一个新类,并添加任何您想要的成员,然后用您的自定义TStringList替换原始TStringList。这样,您的排序例程可以将其List参数类型转换为派生类,以访问您添加到其中的额外成员。
例如,在这种情况下,TFilesSorter本身可以是新的TStringList后代,例如:

TFilesSorter = class(TStringList)
public
  constructor Create(ExtOrderList: TStrings);
  function SoryByExt(List: TStrings);
private
  ExtOrder: TStrings;
end;

constructor TFilesSorter.Create(ExtOrderList: TStrings);
begin
  inherited Create;
  ExtOrder := ExtOrderList;
end;

function doSoryByExt(List: TStringList; Index1, Index2: Integer): Integer;
begin
  // use TFilesSorter(List).ExtOrder to compare
  // List.Strings[Index1] with List.Strings[Index2]
  // as needed...
  Result := ...;
end;

function TFilesSorter.SoryByExt(List: TStrings);
begin
  Self.Assign(List);
  Self.CustomSort(doSoryByExt);
  List.Assign(Self);
end;

...

FilesSorter := TFilesSorter.Create(ExtensionsList);
try
  FilesSorter.SoryByExt(SomeTStringList);
finally
  FilesSorter.Free;
end;

字符串

dy2hfwbg

dy2hfwbg2#

实际上,CustomSort只接受常规函数作为参数,而不是类方法。
你可以解决这个问题,并继续使用TStringList.CustomSort,通过使用一个 Delphi 单元也是一个封装的事实,它很好地隐藏了实现细节。你可以查看一个单元的interface部分,就像一个类的public部分一样,单元的implementation部分类似于类的private部分。单元的initializationfinalization部分对应于类的构造函数和析构函数。
当然,一个单元只能存在一个示例,所以这种模式对应于类的单例模式,其中只创建类的一个对象。
以下是您的问题的可能解决方案:

unit FilesSorter;

interface

uses
  System.Classes;

procedure SetFilesSorterExtList(ExtOrderList: TStrings);
function SortByExt(List: TStringList; Index1, Index2: Integer): Integer;

implementation

var
  FilesExtOrderList: TStringList;

procedure SetFilesSorterExtList(ExtOrderList: TStrings);
begin
  FilesExtOrderList.Clear;
  FilesExtOrderList.AddStrings(ExtOrderList);
end;

function SortByExt(List: TStringList; Index1, Index2: Integer): Integer;
begin
  // ... Implement comparison logic ...
end;

initialization
  FilesExtOrderList := TStringList.Create;
finalization
  FilesExtOrderList.Free;
end.

字符串

相关问题