记录类型(或数组)的前向声明

Forward declarations for record types (or arrays)

我想在 XE5 中执行此操作:

type
  TMyRec = record
    // fields
    class function GetList: TMyRecArr; static;
  end;

  TMyRecArr = array of TMyRec;

我已经看过 "Forward declarations for record types" and "how to do a typed forward declaration?",但它们似乎无关紧要,因为我的问题不是将记录作为参数传递。

您不能使用前向声明来声明记录类型或数组类型。但不要害怕。您可以使用通用动态数组 TArray<T>.

type
  TMyRec = record
    class function GetList: TArray<TMyRec>; static;
  end;

这实际上比根据您问题中的代码声明 TMyRecArr 更好。这是因为泛型 TArray<T> 比传统的动态数组类型具有更灵活的类型标识。您可以将 TArray<T> 与在独立且不知道您的代码的库中定义的泛型类型一起使用。

现在,您可以这样声明类型:

type
  TMyRec = record
    type TMyRecArray = array of TMyRec;
    class function GetList: TMyRecArray; static;
  end;

然后你的数组类型是TMyRec.TMyRecArray。但我劝你不要这样做。您将拥有一个只能与您的代码一起使用而不能与第三方代码一起使用的类型。

综上所述,TArray<T>是你的朋友。

由于允许在类型定义之前声明指针类型,因此稍微修改您的函数就可以这样做:

type
  PMyRecArr = ^TMyRecArr;

  TMyRec = record
    // fields
    class procedure GetList(const arr: PMyRecArr); static;
  end;

  TMyRecArr = array of TMyRec;

程序实现及其使用如下:

class procedure TMyRec.GetList(const arr: PMyRecArr);
begin
  SetLength(arr^, 4);
end;

var
  arr: TMyRecArr;

begin
  TMyRec.GetList(@arr);
  Writeln(Length(arr));//prints 4
end.

好吧,我搜索了一下,发现我可以使用助手来做这个:

type
  TMyRec = record
    // fields
  end;

  TMyRecArr = array of TMyRec;

  TMyRecHelper = record helper for TMyRec
    class function GetList: TMyRecArr; static;
  end;

当然它缺乏 David 在他的回答和评论中提到的泛型的好处,但它不会使代码自动完成无法使用!我的意思是,有人可能会得出这样的结论,即某些代码段不需要 TArray<T> 提供的灵活性。那就无非就是increment in memory usage of the final running application or possibly lower performance.

与其尝试向记录添加前向 decalrations(到目前为止,这在 Delphi 中仍然不可能),有一种解决方法:将引用另一种记录类型的函数移动到记录助手, 在两种记录类型都在范围内的位置声明。

type
  RecordA = record
    // [...]
  end;

  RecordB = record
    // [...]
  end;

  RecordAHelper = record helper for RecordA
    procedure Call(argument: RecordB);
  end;

在明显实现这个之后,上面允许一个人写(编译和运行):RecordA_variable.Call(RecordB_variable)