Как назначить перегруженный метод класса анонимному методу?

В Delphi мы можем назначить метод класса (объявленный как procedure of object) как параметр типа анонимного метода.

Для перегруженных методов (с одинаковыми именами методов) передача метода объекта завершается с ошибкой компиляции:

[dcc32 Error] Project56.dpr(40): E2010 Incompatible types: 'System.SysUtils.TProc<System.Integer,System.Integer>' and 'Procedure of object'

Следующий пример показывает ситуацию. Возможно ли, чтобы перегруженный метод передавался как параметр анонимного метода?

type
  TTest = class
  public
    procedure M(a: Integer); overload;
    procedure M(a, b: Integer); overload;
  end;

procedure TTest.M(a, b: Integer);
begin
  WriteLn(a, b);
end;

procedure TTest.M(a: Integer);
begin
  WriteLn(a);
end;

procedure DoTask1(Proc: TProc<Integer>);
begin
  Proc(100);
end;

procedure DoTask2(Proc: TProc<Integer,Integer>);
begin
  Proc(100, 200);
end;

begin
  var o := TTest.Create;
  DoTask1(o.M);  // <-- Success
  DoTask2(o.M);  // <-- Fail to compile: E2010 Incompatible types: 'System.SysUtils.TProc<System.Integer,System.Integer>' and 'Procedure of object'
  ReadLn;
end.

Ответы

Ответ 1

Когда ты пишешь

DoTask2(o.M);

Компилятор видит, что o.M не является анонимным методом, и генерирует его для вас за кулисами, который оборачивает вызов к o.M. К сожалению, он не может искать перегруженные методы при этом, следовательно, ошибка компиляции.

Решение состоит в том, чтобы вручную создать оболочку анонимного метода.

DoTask2(
  procedure(a, b: Integer) 
  begin
    o.M(a, b);
  end 
);

Это именно то, что компилятор делает для вас за кулисами, когда оборачивает стандартный метод анонимным методом. Таким образом, хотя синтаксис утомителен, конечный результат идентичен во время выполнения.