在Delphi XE2的帮助下System.Generics.Collections.TArray.Sort,它说
Note: If the Comparer parameter is provided, it is used to compare elements; otherwise the default comparator for the array elements is used.
Run Code Online (Sandbox Code Playgroud)
我挖回位,发现默认比较TArray.Sort是_LookupVtableInfo从System.Generics.Defaults.这个代码是
function _LookupVtableInfo(intf: TDefaultGenericInterface; info: PTypeInfo; size: Integer): Pointer;
var
pinfo: PVtableInfo;
begin
if info <> nil then
begin
pinfo := @VtableInfo[intf, info^.Kind];
Result := pinfo^.Data;
if ifSelector in pinfo^.Flags then
Result := TTypeInfoSelector(Result)(info, size);
if ifVariableSize in pinfo^.Flags then
Result := MakeInstance(Result, size);
end
else
begin
case intf of
giComparer: Result := Comparer_Selector_Binary(info, size);
giEqualityComparer: Result := EqualityComparer_Selector_Binary(info, size);
else
System.Error(reRangeError);
Result := nil;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
它被称为
IComparer<T>(_LookupVtableInfo(giComparer, TypeInfo(T), SizeOf(T)))
Run Code Online (Sandbox Code Playgroud)
我已经仔细研究了这一点,但我并不确定我知道它的作用.它只是将内存中的位相互比较或者究竟是什么?
问题的第二部分是一个更普遍的问题,你可能真正想要使用默认比较器,或者你不太可能真的想要使用它?
默认比较器提供了许多常见类型的实现.具体来说它支持以下内容:
Byte,Word,Integer等.对于其中许多类型,默认实现正是您所期望的.例如,对于整数,枚举类型,浮点类型的实现使用<,>和=运营商.对于string默认的实现调用CompareStr.
对于其他类型,默认实现可能不太有用.例如,对于记录,比较是逐字节二进制比较.您很可能希望为记录提供自己的比较器实现.注意记录的一件事是默认比较器将比较记录中的任何填充,你永远不想这样做.因此,对于具有填充的对齐记录,它永远不会有用.我还会对包含引用类型的记录的实用程序提出质疑.
对于动态数组,默认实现首先比较长度,然后,如果length相等,则比较数组的二进制内容.因此,对于简单值类型的数组而言,这可能是合理的.但对于多维动态数组或引用类型数组,并非如此.
对于类实例,方法,过程变量,接口,默认比较器将操作数视为指针(在方法的情况下为两个指针)并执行地址比较.
如果要使用默认比较器?那么,只要符合比较器的要求,就可以使用它.因此,简单的值类型肯定有意义.除此之外,您需要根据具体情况做出决定.
你在那里发布的函数实际上并不是比较函数,而是一个基于TypeInfo和SizeOf T返回比较函数的函数.
更深层次的,我们在Generics中看到.默认的形式有很多功能:
function Compare_类型名称(Inst: Pointer; const Left, Right:类型): Integer;
它们都有相同的主体(但左右注释有不同的类型)
begin
if Left < Right then
Result := -1
else if Left > Right then
Result := 1
else
Result := 0;
end;
Run Code Online (Sandbox Code Playgroud)
最后还剩下一切
function BinaryCompare(const Left, Right: Pointer; Size: Integer): Integer;
var
pl, pr: PByte;
len: Integer;
begin
pl := Left;
pr := Right;
len := Size;
while len > 0 do
begin
Result := pl^ - pr^;
if Result <> 0 then
Exit;
Dec(len);
Inc(pl);
Inc(pr);
end;
Result := 0;
end;
Run Code Online (Sandbox Code Playgroud)