Anonymous methods in Delphi: the internals

Barry Kelly has explained in his recent post how to obtain a method pointer from an anonymous method. Here I will play a little more with the anonymous methods (using Delphi 2009) and consider a somewhat reversed problem – how to create an anonymous method that incapsulates the ordinary function.

First how it is done in the “normal” way:

type
  TIntFunc = function(Value: Integer): Integer;
  TIntFuncRef = reference to function(Value: Integer): Integer;

function Square(Value: Integer): Integer;
begin
  Result:= Value * Value;
end;

function MakeAnonMethod(AFunc: TIntFunc): TIntFuncRef;
begin
  Result:= function(Value: Integer): Integer
  begin
    Result:= AFunc(Value);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  AnonMethod: TIntFuncRef;

begin
  AnonMethod:= MakeAnonMethod(@Square);
  ShowMessage(IntToStr(AnonMethod(2)));
end;

The MakeAnonMethod function creates the anonymous method that captures a function variable (AFunc argument, actually a pointer). That is simple.

Now let us consider what is going on behind the scene. An anonymous method is internally an interface with a single method “Invoke”:

type
  TAnonCaller = class(TInterfacedObject, TIntFuncRef)
  private
    FFunc: TIntFunc;
    function Invoke(Value: Integer): Integer;
  public
    constructor Create(AFunc: TIntFunc);
  end;

constructor TAnonCaller.Create(AFunc: TIntFunc);
begin
  FFunc:= AFunc;
end;

function TAnonCaller.Invoke(Value: Integer): Integer;
begin
  Result:= FFunc(Value);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  AnonMethod: TIntFuncRef;

begin
  AnonMethod:= TAnonCaller.Create(@Square);
  ShowMessage(IntToStr(AnonMethod(2)));
end;

The second code snippet do the same thing as the first – it “captures” the function variable in TAnonCaller.Create constructor and uses it to call the “captured” function.
The above code snippets show that

  • when we create an anonymous method we actually create an object that implements an interface of a special kind and obtain a reference to the interface
  • when we call the anonymous method we actually call the Invoke method of the interface.

The above is an oversimplified description of how the anonymous methods work internally. A more closer look at anonymous methods shows that several anonymous methods may share a single object implementing the interfaces for all of them, and that is the way how the different anonymous methods share the captured variables (as fields of the common object).

2 thoughts on “Anonymous methods in Delphi: the internals

  1. You don’t need to do that. This line will work just as well:

    AnonMethod := Square;

    Method references are designed to be assignment compatible on input with methods, functions, method pointers, function pointers and anonymous methods.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s