E2555无法捕获符号“自我”

时间:2019-01-11 11:37:51

标签: delphi anonymous-methods

运行以下代码时,我得到E2555 Cannot capture symbol 'Self'

type
  TLookupTable = record
    FData: TArray<TOtherRec>;
    procedure ReverseLeftToRight;
  end;

procedure TLookupTable.ReverseLeftToRight;
begin
  Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
    FData[i]:= FData[i].ReverseLeftRight;
  end); {for i}
end;

该如何解决?

1 个答案:

答案 0 :(得分:0)

问题是var参数(包括Self的隐藏var参数)没有被捕获。但是,我们不想复制该记录,这将是无用的,因为那样我们的方法将无法工作。

使隐藏的self参数明确的技巧。
如果这是一个类,那么很容易(var S:= Self),否则,就必须声明一个指向记录的指针。

procedure TLookupTable.ReverseLeftToRight;
type 
  PLookupTable = ^TLookupTable;
var
  S: PLookupTable;
begin
  S:= @Self;
  Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
    S.FData[i]:= S.FData[i].ReverseLeftRight;
  end); {for i}
end;

现在,编译器不再抱怨。
(请注意,我正在对S^.xyz使用隐式语法)。

Delphi Rio
使用如下所示的内联var声明不起作用。

  //S: PLookupTable;
begin
  var S:= @Self; //inline declaration
  Parallel.For(0, Length(FData)-1).NoWait.Execute(procedure(i: integer) begin
    S.FData[i]:= S.FData[i].ReverseLeftRight;
  end); {for i}

这将生成:E2018 Record, object or class type required
我猜内联@Self被解析为通用指针,这很可惜,因为有足够的信息来推断内联变量的正确类型。

异步问题
如果使用异步(.NoWait)线程/任务执行代码,则最好将FData放在本地变量中。作为动态数组的FData已经是一个指针(因此不会进行复制,而只是引用计数)。而且动态数组没有写时复制语义,因此原始数组将得到更新。
照原样,Self记录可能在代码运行时超出范围,从而导致访问冲突(或更糟)。