我有以下方法:
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>
传递给自然不通过编译时检查的方法。
答案 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的好处是否值得这种歧义的缺点?在我看来,事实并非如此。