是否可以初始化函数的常量引用数组?

Pap*_*aya 1 delphi delphi-10.1-berlin

在阅读了Embarcadero关于程序类型匿名方法的文档以及David Heffernan对此问题的解释后,我仍然不太明白为什么编译器禁止初始化函数的常量引用数组,如下例中的C_BAR.

program MyProgram;

{$APPTYPE CONSOLE}

{$R *.res}

type
  TFoo = function: Integer;
  TBar = reference to function: Integer;

  function FooBar: Integer;
  begin
    Result := 42;
  end;

const
  // This works
  C_FOO: array[0..0] of TFoo = (FooBar);

  // These lines do not compile
  // C_BAR: array[0..0] of TBar = (FooBar); // TBar incompatible with Integer
  // C_BAR: array[0..0] of TBar = (@FooBar); // TBar incompatible with Pointer

var
  Foo: array[0..0] of TFoo;
  Bar: array[0..0] of TBar;
begin
  Foo[0] := FooBar; // Foo[0] = MyProgram.FooBar
  Bar[0] := FooBar; // Bar[0] = MyProgram$1$ActRec($1CC8CF0) as TBar

  Foo[0] := C_FOO[0]; // Foo[0] = MyProgram.FooBar
  Bar[0] := C_FOO[0]; // Bar[0] = MyProgram$1$ActRec($1CC8CF0) as TBar
end.
Run Code Online (Sandbox Code Playgroud)

使用调试器,我可以看到Bar [0]等于某个地址(我想?),这告诉我在我的理解背后发生了一些事情......

那么在我的例子中是否可以初始化像C_BAR这样的常量数组?如果是,怎么做,否则,为什么?

Dav*_*nan 7

相关文档在关于类型常量的部分中:

与常量不同,类型常量可以包含数组,记录,过程和指针类型的值.类型常量不能出现在常量表达式中.

声明一个类型化的常量,如下所示:

const identifier: type = value
Run Code Online (Sandbox Code Playgroud)

其中identifier是任何有效的标识符,type是除文件和变体之外的任何类型,value是类型的表达式.例如,

const Max: Integer = 100;
Run Code Online (Sandbox Code Playgroud)

在大多数情况下,价值必须是一个恒定的表达; 但如果type是数组,记录,过程或指针类型,则应用特殊规则.

这些特殊规则是程序类型如下:

要声明过程常量,请指定与常量的声明类型兼容的函数或过程的名称.例如,

function Calc(X, Y: Integer): Integer;
begin
  ...
end;
type TFunction = function(X, Y: Integer): Integer;
const MyFunction: TFunction = Calc;
Run Code Online (Sandbox Code Playgroud)

给定这些声明,您可以在函数调用中使用过程常量MyFunction:

I := MyFunction(5, 7)
Run Code Online (Sandbox Code Playgroud)

您还可以将值nil赋值给程序常量.

这就解释了为什么你可以声明一个类型化的常量TFoo.

至于匿名方法,它们未在本文档中的任何位置列出.现在,匿名方法被实现为接口.该接口具有由编译器生成的支持类,因此需要创建该类的实例.该实例是在堆上分配的,这是(至少一个原因)为什么你不能将匿名方法声明为常量.