作为方法参数传递时如何避免评估 TFunc<TProc<T>>?

How to avoid evaluation of TFunc<TProc<T>> when passing as method argument?

我有以下方法:

InstanceOfMyType(const Name: String; const Modifiers: array of TFunc<TProc<TMyType>>);

想法是在单元测试中允许流畅的设置代码。

当我尝试调用该方法时出现问题:

// in test helper methods
function TTest.WithSomeProperty: TProc<TMyType>
begin
Result := 
  procedure (MyType: TMyType)
  begin
  // modify MyType instance
  end;      
end;

// in the test
Given;
  InstanceOfMyType('Name', WithSomeProperty);

有什么方法可以强制编译器不评估传递的 TFunc 并产生编译时错误?

[DCC Error] IndexerTests.pas(257): E2010 Incompatible types: 'array of System.SysUtils.TFunc<System.SysUtils.TProc<TMyType>>' and 'System.SysUtils.TProc<TMyType>'

WithSomeProperty 显然是一个 TFunc<TProc<TMyType>> 但编译器总是对其求值并尝试将结果 TProc<TMyType> 传递给自然不会通过编译时检查的方法。

此程序在 XE2 上编译并输出 12:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

function GetProc: TProc<Integer>;
begin
  Result :=
    procedure(Value: Integer)
    begin
      Writeln(Value);
    end;
end;

procedure CallProc(const GetProcArr: array of TFunc<TProc<Integer>>);
begin
  GetProcArr[0]()(666);
end;

begin
  CallProc([GetProc]);
  Readln;
end.

通常情况下,您可以在为开放数组参数准备实参时省略方括号,编译器会将其转换为单个元素数组。但这似乎会使编译器与此参数类型混淆。

在 XE2 中,

CallProc(GetProc);

导致您报告的 E2010 编译错误。

XE7

CallProc(GetProc);

编译但随后导致运行时错误。很明显,仍然存在与将单个值转换为单个元素开放数组参数的未记录功能相关的编译器错误。

不幸的是,这种混乱是语言设计者决定允许您在函数调用中省略括号的直接结果。虽然这确实会产生可以说更具可读性的代码,但有时确实会使编译器处于表达式不明确的情况下。这里就是这种情况,您必须明确解决歧义。在调用函数时省略括号的好处是否值得这种歧义的缺点?在我看来并非如此。