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).

About these ads

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