Проблема в том, что var
параметры (включая скрытые параметры var для Self
) не фиксируются. Однако мы не хотим копировать записи, что было бы бесполезно, потому что тогда наш метод не будет работать.
Хитрость, чтобы сделать скрытый параметр 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
).
Дельфи Рио
Использование встроенного объявления 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
разрешается в общий указатель, что является позором, потому что есть достаточно информации, чтобы вывести правильный тип для встроенной переменной.
Асинхронные проблемы
Если вы выполняете код, используя поток / задачу Async (.NoWait
), то может быть лучше поместить FData
в локальную переменную. FData, будучи динамическим массивом, уже является указателем (поэтому копирование не будет, только подсчет ссылок). А динамические массивы не имеют семантики копирования при записи, поэтому оригинал будет обновляться.
Таким образом, запись Self
может выйти из области видимости во время выполнения кода, что приведет к нарушению доступа (или хуже).