I'm trying to use an array of Integer
parameter inside an anonymous method passed as parameter to another function:
type
TAnonymousMethod = reference to procedure();
procedure SubTest(AMethod : TAnonymousMethod);
begin
AMethod();
end;
procedure Test(ACodes : array of Integer);
begin
SubTest(
procedure()
begin
ShowMessage(IntToStr(Length(ACodes)));
end
);
end;
On compiling it produces the following E2555 error:
[dcc32 Error] Unit1.pas(38): E2555 Cannot capture symbol 'ACodes'
I've tried to do the same thing using one only Integer
value and it compiled without errors.
procedure Test(ACode : Integer);
begin
SubTest(
procedure()
begin
ShowMessage(IntToStr(ACode));
end
);
end;
So the problem seems to be related to the open array parameters only.
Why does this happen and how could it be avoided?
Open arrays are implemented as actually two parameters, the first one being the pointer to the first element, and the second being the highest index.
Knowing this, it becomes clear why such a thing cannot be captured, as the captured value could potentially outlive the original lifetime.
Yes, you can capture other things that potentially outlive their lifetime due to being captured, but in those cases that is because you explicitly destroyed an object for example, or freed some memory, but not because of how it was passed to some routine. Capturing always makes sure that the value is kept alive for at least the same time as the closure lives.
Captured values in a closure are internally implemented as fields in the closure backing object that the compiler creates, and so there is basically an assignment happening from the captured values to these fields (simply said). Open array parameters cannot be assigned to a local variable or similar, only accessed like an array, or passed on further.