delphi - 如何通过 TComparer类到Delphi中的泛型类型?
问题描述
我想创建具有某些功能的通用记录,包括搜索功能。为了执行这个搜索,我想传递一个自定义的比较器来比较项目。如果它是一个类,我可以在构造函数中传递它,但我想使用记录来避免创建或释放它。所以,我没有一个构造函数来初始化比较器。
然后我决定像 Type 参数一样传递 Comparer 类,当我需要比较器时,使用 TComparer.Default 创建比较器的实例。
好吧,这里是代码:
TMyArray<T,C: TComparer<T>> = record
FComparer: IComparer<T>;
Items: TArray<T>;
function Contains<AItem: T>: Boolean;
end;
当我尝试以这种方式使用它时出现问题:
TMyRecord = record
Score: Real;
A: string;
B: string;
end;
TMyRecordComparer = class(TComparer<TMyRecord>)
function Compare(Left, Right: TMyRecord): Integer;
end;
TMyRecordArray = TMyArray<TMyRecord, TMyRecordComparer>;
使用最后一个声明,我收到此错误:E2515 类型参数“T”与类型“System.Generics.Defaults.TComparer\”不兼容。
知道如何解决这个问题吗?
解决方案
虽然大卫的回答解决了编译错误的问题,但我实际上会使用不同的约束:
TMyArray<T; C: class, constructor, IComparer<T>> = record
这意味着C
必须是一个具有无参数构造函数并实现IComparer<T>
接口的类。这稍微放宽了约束,因为您不必继承比较器,System.Generics.Collections.TComparer<T>
而只需实现所需的IComparer<T>
接口。
此外,fwiw,使用您的问题中发布的代码,您将收到 W1010 警告,这意味着您缺少对您的TMyRecordComparer.Compare
方法的覆盖(以及它的缺失const
)。如果您从使用虚拟抽象方法TComparer<T>
实现的继承,则需要这样做。IComparer<T>
您使用的想法.Default
也行不通,因为该想法为 type 的比较器创建了默认实现T
。但是您想使用您指定的自定义。
所以有了我上面写的约束,你可以做这样的事情(天真的非线程安全实现):
function TMyArray<T, C>.Contains<AItem>: Boolean;
begin
if FComparer = nil then
FComparer := C.Create;
// ....
end;
最后但并非最不重要的一点是,我不确定您的Contains
方法是否正确 - 您编写它的方式表明您要检查您的数组是否包含AItem
类型T
或子类型的类型元素(或者是否T
是接口类型,实现T
) - 我猜你打算写
function Contains(AItem: T): Boolean;
推荐阅读
- assembly - 如何将号码从寄存器转移到标签?
- aws-cdk - aws-cdk TokenAuthorizer - 如何将有效负载从授权方传递到受保护端点的 lambda?
- django - mod_rewrite + django 导致登录后重定向 URL 不正确
- java - 如何让程序回到某一行?
- php - Wordpress 缩略图作为背景图像,带有默认的后备
- r - 我在图表中的边距正在切断我的图表?
- r - 如何组合柱形图
- google-apps-script - 谷歌表格每天跟踪一个单元格的值
- java - Hibernate 尝试在没有任何级联的情况下插入一对一的关系
- sql - 在 Bigquery 中按用户计算登录之间的时间