如何避免评估TFunc <tproc <t>&gt;当作为方法参数传递时?</tproc <t>

时间:2015-03-09 09:07:02

标签: delphi delphi-xe2

我有以下方法:

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>传递给自然不通过编译时检查的方法。

1 个答案:

答案 0 :(得分:5)

该程序在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);

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

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