[英]How to pass a TComparer<T> class to a generic type in Delphi?
我想创建一个具有一些功能的通用记录,包括搜索功能。 要执行此搜索,我想传递一个自定义Comparer来比较项目。 如果它是一个类,我可以在构造函数中传递它,但我想使用一个记录来避免创建或释放它。 所以,我没有构造函数初始化Comparer。
然后我决定像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 \\'不兼容。
不知道如何解决这个问题?
虽然David的答案解决了编译错误的问题,但实际上我会使用不同的约束:
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>
继承, TComparer<T>
因为它使用虚拟抽象方法实现IComparer<T>
。
您使用.Default
想法也不会起作用,因为它为类型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;
问题是约束的语法:
TMyArray<T,C: TComparer<T>>
这将T
和C
都限制为TComparer<T>
。
相反,你需要这个:
TMyArray<T; C: TComparer<T>>
该文档提供了各种语法选项的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.