Delphi 传递给内联函数的匿名函数
Delphi anonymous function passed to inlined function
我偶然发现了一个意想不到的 Delphi 2009 行为。在调查了我的代码中的一个奇怪错误后,我设法缩小了问题的范围并创建了一个最小示例,我将在下面展示。
当然,下面的代码打印值1:
program Example1;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
end.
同样,这个程序打印值 2:
program Example2;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 2;
end, 0));
end.
"Obviously",第三个程序打印与第一个相同的值,即 1:
program Produce;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
fcn(function(const X: integer): integer
begin
result := 2;
end, 0); // discard the output
end.
但是,输出不是 1,而是 2。似乎编译器在 writeln
中对 fcn
的调用中使用了第二个匿名函数。
对我来说,这似乎是 Delphi 2009 编译器中的一个错误,但也可能只是我不理解 Delphi 中有关匿名函数的更微妙的细节。你怎么看?
这显然是一个错误,根据收到的问题评论,这已在 Delphi XE 中修复。可能最简单的解决方法是在编译器无法正确处理时跳过请求内联:
program Solve;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer;
{$IF CompilerVersion >= 22}inline;{$IFEND} {Warning: Horrible bug in Delphi 2009}
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
fcn(function(const X: integer): integer
begin
result := 2;
end, 0); // discard the output
end.
在大多数情况下,性能损失在 Delphi 2009 中应该可以忽略不计,并且您在 XE 和更高版本中确实请求内联。当然,如果您认为内联根本不重要,您可以简单地完全删除请求。
我偶然发现了一个意想不到的 Delphi 2009 行为。在调查了我的代码中的一个奇怪错误后,我设法缩小了问题的范围并创建了一个最小示例,我将在下面展示。
当然,下面的代码打印值1:
program Example1;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
end.
同样,这个程序打印值 2:
program Example2;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 2;
end, 0));
end.
"Obviously",第三个程序打印与第一个相同的值,即 1:
program Produce;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer; inline;
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
fcn(function(const X: integer): integer
begin
result := 2;
end, 0); // discard the output
end.
但是,输出不是 1,而是 2。似乎编译器在 writeln
中对 fcn
的调用中使用了第二个匿名函数。
对我来说,这似乎是 Delphi 2009 编译器中的一个错误,但也可能只是我不理解 Delphi 中有关匿名函数的更微妙的细节。你怎么看?
这显然是一个错误,根据收到的问题评论,这已在 Delphi XE 中修复。可能最简单的解决方法是在编译器无法正确处理时跳过请求内联:
program Solve;
{$APPTYPE CONSOLE}
type
TIntFcn = reference to function(const X: integer): integer;
function fcn(AFunction: TIntFcn; a: integer): integer;
{$IF CompilerVersion >= 22}inline;{$IFEND} {Warning: Horrible bug in Delphi 2009}
begin
result := AFunction(a);
end;
begin
writeln(fcn(function(const X: integer): integer
begin
result := 1;
end, 0));
fcn(function(const X: integer): integer
begin
result := 2;
end, 0); // discard the output
end.
在大多数情况下,性能损失在 Delphi 2009 中应该可以忽略不计,并且您在 XE 和更高版本中确实请求内联。当然,如果您认为内联根本不重要,您可以简单地完全删除请求。