Articles Delphi: Pitfalls of Anonymous methods and Capture by Lars Fosdal

emailx45

Social Engineer
Joined
May 5, 2008
Messages
2,387
Reaction score
2,149
Delphi: Pitfalls of Anonymous methods and Capture
Lars Fosdal - 08/Feb2019
[SHOWTOGROUPS=4,20]
I was writing a web request handler when I ran into a problem. I was plugging in multiple handlers, but only one of them actually worked.

Why?

To get to the essence of it, this doesn’t work

Code:
procedure TMyClass.Setup;
var
  Handler: THandlerClass;
  hType  : THandlers;
begin
  Broker.Clear;
  for hType in [foo, bar] do
  begin
    case hType of
      foo:
        Handler := TFoo.Create;
      bar:
        Handler := TBar.Create;
    end;
    Broker.AddHandler(Handler.OnHandle);
  end;
end;

Zipped example source code (12/May/2020 online) : https://drive.google.com/open?id=1RxOxOlYOrjqPryW7vGNw40VTLav6IN_M

The handler will always be the “bar” handler, probably because it is last.

So, what works? Moving the creating and adding to the list to a separate method.

Code:
function TMyClass.WithProc<T>: T;
var
  Handler: T;
begin
  Handler := T.Create;
  Broker.AddHandler(Handler.OnHandle);
end;

procedure TMyClass.Setup;
var
  hType: THandlers;
begin
  Broker.Clear;
  for hType in [foo, bar] do
  begin
    case hType of
      foo:
        WithProc<TFoo>;
      bar:
        WithProc<TBar>;
    end;
  end;
end;

It behaves the same in both Tokyo and Rio.

Now – here is my question… Is this as expected or a bug ?

Update: The answer is – as expected. The reason is that the capture grabs a reference to the Variable, not to the value of the variable, hence the value of the Variable value will be the same for all captures, and the same as the last value set.

Personally, I would have liked to see the compiler issue a hint or a warning for captures in a loop.

[/SHOWTOGROUPS]
 

Bartram

New member
Joined
Aug 14, 2007
Messages
3
Reaction score
0
"Hey Lars, thanks for sharing your insights on anonymous methods and capture. I've had my share of 'gotchas' with them, especially when working with closures. Can you elaborate on how to avoid this pitfall in Delphi?"
 
Top