在Delphi中将字段记录为过程的形式参数

问题描述 投票:0回答:1

我想创建一个对变量记录类型执行一些操作的过程。在全球范围内,我有一系列记录。我想对数组进行排序,但要按记录的字段进行排序。我想将该字段作为参数传递给过程。问题是:

如何将记录的字段作为参数传递?例如:函数

f2
应返回字段的值字段的偏移量。

type  TCell = record
    a: byte;
    b: byte;
  end;

function f2(cell: Tcell; offset: byte): byte;
begin
   { ** } result:=cell.offset { ** }
end;

begin
    c: TCell;
    c.a:=10; c.b:=20;
    writeln(f2(c, 2))  // 20;
end;

在Delphi中可以吗?在 FreePascal 中通过指针当然是可能的,但以下内容在 Delphi 中不起作用,并且编译器会引发错误:

E2015“运算符不适用于此操作数类型”

function f1(a: pointer; offset: integer): byte;
begin
  f1 := PByte(a+offset)^;  // ← error here
end;

begin
    cell.a:=10; cell.b:=20; 
    writeln(f1(@cell,0));          
    writeln(f1(@cell,1));
end.
pointers delphi record freepascal
1个回答
4
投票

好吧,让我先回答你的“实际”问题:

在全球范围内,我有一系列记录。我想对数组进行排序,但是按记录的字段排序。

在现代版本的 Delphi 中,您可以使用泛型来实现此目的:

type
  TCell = record
    a, b: Byte
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  var Arr := TArray<TCell>(nil);

  TArray.Sort<TCell>(
    Arr,
    TComparer<TCell>.Construct(
      function(const Left, Right: TCell): Integer
      begin
        Result := Left.a - Right.a // no overflow risk
      end
    )
  );

end;

我想将该字段作为过程的参数传递。

为各个字段创建枚举类型并使用

case
语句。

您也可以使用 RTTI,但性能不会那么好。

在 Pascal 中通过指针当然是可能的

您也可以在 Delphi 中使用指针,但这很少是好的做法,除非您是 Delphi 专家并且确实需要绝对最佳的性能或最出色的代码。

type
  TCell = packed record
    a, b: Byte
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  var Cell := Default(TCell);

  Cell.a := 100;
  Cell.b := 200;

  var p := PByte(@Cell);

  ShowMessage(p^.ToString);
  ShowMessage((p + 1)^.ToString);

end;

这里的技巧是

PByte
是在指针算术开启的情况下声明的。事实上,在
System.pas
你会发现

  {$POINTERMATH ON}
  PByte         = ^Byte;        {$NODEFINE PByte}       { defined in sysmac.h }
  {$POINTERMATH OFF}

您始终可以在自己的指针类型上使用此技巧。

您的代码

  f1 := PByte(a+offset)^;  //<--- error here

不起作用,因为

a
Pointer
offset
Integer
,而你不能
+
Pointer
Integer

但是

  PByte(PByte(a) + offset)^

会起作用。

© www.soinside.com 2019 - 2024. All rights reserved.