Pau*_*aul 8 delphi generics 64-bit delphi-xe2
在32位与64位下编译时,TPair的默认排序似乎存在差异.在32位下,默认排序的行为就像它在对的Key上排序一样,在64位下,它看起来按值排序.这是预期的,还是我错过了什么?
使用Delphi XE2测试,更新4.在VCL应用程序中,将按钮,复选框和列表框拖放到屏幕上,声明以下类型
type TPairComparer = TComparer<TPair<integer,integer>>;
Run Code Online (Sandbox Code Playgroud)
然后将下面的代码放在OnClick按钮上并运行.在32位下,使用默认排序,按键列出对,即1,2,3,4,5,6.在64位下,这些对按值列出,即2,5,6,7,8,9,而不是按键.
为了使代码在两个平台上一致地工作,我需要指定我自己的比较器来强制在64位可执行文件上按键排序.
procedure TForm1.Button1Click(Sender: TObject);
var PriorityList : TList<TPair<Integer,integer>>;
Pair : TPair<integer,integer>;
PairComparer : IComparer<TPair<integer,integer>>;
iLoop : integer;
begin
PriorityList := TList<TPair<Integer,integer>>.Create;
PairComparer := TPairComparer.Construct(
function(const Left, Right: TPair<integer,integer>): Integer
begin
case Left.Key = Right.Key of
true : Result := 0;
else case Left.Key < Right.Key of
true : Result := -1;
else Result := +1;
end;
end;
end);
Pair.Key := 6;
Pair.Value := 6;
PriorityList.Add(Pair);
Pair.Key := 5;
Pair.Value := 5;
PriorityList.Add(Pair);
Pair.Key := 4;
Pair.Value := 8;
PriorityList.Add(Pair);
Pair.Key := 3;
Pair.Value := 9;
PriorityList.Add(Pair);
Pair.Key := 2;
Pair.Value := 7;
PriorityList.Add(Pair);
Pair.Key := 1;
Pair.Value := 2;
PriorityList.Add(Pair);
case Checkbox1.Checked of
true : PriorityList.Sort;
false : PriorityList.Sort(PairComparer);
end;
ListBox1.Clear;
for iLoop := 0 to PriorityList.Count-1 do
ListBox1.Items.Add(Format('Key : %d , Value : %d',[PriorityList[iLoop].Key,PriorityList[iLoop].Value]));
Run Code Online (Sandbox Code Playgroud)
结束;
这种类型的默认比较器非常随意.编译器不使用任何记录组成的知识.您当然没有告诉它您希望哪个成员成为主要的排序键.所以它可以自由地做它想要的东西.
在32位中,8字节记录的默认比较器是通过调用类似CompareMem函数来实现的.因此,字节以递增的地址顺序进行比较.因此,关键是更重要的.
在64位下,默认比较器将该类型视为无符号64位整数,因此以递减的地址顺序比较字节,这是小端.因此价值更重要.
相关代码在以下的实现部分中Generics.Defaults:
function Comparer_Selector_Binary(info: PTypeInfo; size: Integer): Pointer;
begin
case size of
// NOTE: Little-endianness may cause counterintuitive results,
// but the results will at least be consistent.
1: Result := @Comparer_Instance_U1;
2: Result := @Comparer_Instance_U2;
4: Result := @Comparer_Instance_U4;
{$IFDEF CPUX64}
// 64-bit will pass const args in registers
8: Result := @Comparer_Instance_U8;
{$ENDIF}
else
Result := MakeInstance(@Comparer_Vtable_Binary, size);
end;
end;
Run Code Online (Sandbox Code Playgroud)
最重要的是,只要您希望对记录进行排序,就需要提供真正的比较器.只有内置数字和字符串类型才有明确定义的有序比较器.