Delphi匿名函数传递给内联函数

时间:2017-06-02 20:01:48

标签: delphi inline anonymous-function delphi-2009

我偶然发现了意外的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.

"显然",第三个程序打印的值与第一个相同,即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.看起来编译器在fcn的{​​{1}}调用中使用了第二个匿名函数。

对我而言,这似乎是Delphi 2009编译器中的一个错误,但它也可能只是我不了解Delphi中有关匿名函数的更细微的细节。你觉得怎么样?

1 个答案:

答案 0 :(得分:1)

这肯定是一个错误,根据收到的问题的评论,这已在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及更高版本中进行内联。当然,如果你不认为内联很重要,你可以简单地删除请求。