以下代码(仅用于说明问题的代码)可在Delphi 2010中编译并工作。在Delphi 2009中,编译器失败,并显示“ E2035实际参数不足”。

program Project50;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TMyProc = reference to procedure(param: integer);

var
  a: TProc;
  b: TMyProc;

begin
  b := procedure (param: integer)
    begin
    end;
  a := TProc(b); // <-- [DCC Error] Project50.dpr(19): E2035 Not enough actual parameters
end.


我发现只有一个非常难看的技巧可以解决该问题(a:TProc绝对b)。有人知道针对此编译器缺陷的更好的解决方法吗?

[TProc字段实际上隐藏在可以存储各种“可执行”代码-TProcedure,TMethod和TProc的记录内。强制转换用于将特定的匿名proc存储到此字段中。]

最佳答案

我发现了一个黑客#2:

program Project1;

{$APPTYPE CONSOLE}


uses
  SysUtils;

type
  TMyProc = reference to procedure(param: integer);

var
  a: TProc;
  b: TMyProc;

begin
  b := procedure (param: integer)
    begin
      Writeln('asdf');
    end;
  PPointer(@a)^ := PPointer(@b)^;
  a;
  readln;
end.


我怀疑通过将TMyProc(带param参数)分配给TProc(无参数)会达到什么目的?



更新:hack#3(应该增加引用计数器,这个想法从System._IntfCopy中被盗):

procedure AnonCopy(var Dest; const Source);
var
  P: Pointer;

begin
  P:= Pointer(Dest);
  if Pointer(Source) <> nil
    then IInterface(Source)._AddRef;
  Pointer(Dest):= Pointer(Source);
  if P <> nil then
    IInterface(P)._Release;
end;

var
  a: TProc;
  b: TMyProc;

begin
  b := procedure (param: integer)
    begin
      Writeln('asdf');
    end;
  AnonCopy(a, b);
//  PPointer(@a)^ := PPointer(@b)^;
  a;
  readln;
end.

09-12 19:54