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

Is it possible to initialize a constant array of reference to function?

在阅读了 Embarcadero 关于 procedural types & anonymous methods and David Heffernan's explanation 的文档后,我仍然不太明白为什么编译器禁止初始化函数引用的常量数组,如下例中的 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$ActRec(CC8CF0) as TBar

  Foo[0] := C_FOO[0]; // Foo[0] = MyProgram.FooBar
  Bar[0] := C_FOO[0]; // Bar[0] = MyProgram$ActRec(CC8CF0) as TBar
end.

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

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

相关文档位于 Typed Constants 部分:

Typed constants, unlike true constants, can hold values of array, record, procedural, and pointer types. Typed constants cannot occur in constant expressions.

Declare a typed constant like this:

const identifier: type = value

where identifier is any valid identifier, type is any type except files and variants, and value is an expression of type. For example,

const Max: Integer = 100;

In most cases, value must be a constant expression; but if type is an array, record, procedural, or pointer type, special rules apply.

程序类型的特殊规则如下:

To declare a procedural constant, specify the name of a function or procedure that is compatible with the declared type of the constant. For example,

function Calc(X, Y: Integer): Integer;
begin
  ...
end;
type TFunction = function(X, Y: Integer): Integer;
const MyFunction: TFunction = Calc;

Given these declarations, you can use the procedural constant MyFunction in a function call:

I := MyFunction(5, 7)

You can also assign the value nil to a procedural constant.

这就解释了为什么可以使用 TFoo 声明类型常量。

至于匿名方法,它们没有在本文档的任何地方列出。现在,一个匿名方法被实现为一个接口。该接口有一个由编译器生成的支持 class,因此需要创建一个 class 的实例。该实例分配在堆上,这就是(至少一个原因)您不能将匿名方法声明为常量的原因。