Delphi 2010+ и «Левая сторона не может быть назначена» в записях только для чтения: это можно отключить? - PullRequest
0 голосов
/ 01 июля 2011

Я знаю что изменилось .Я знаю почему.Но ..

TComplicatedCallMaker = record
    Param1: TRecordType;
    Param2: TRecordType;
    {...}
    Param15: TRecordType;
    procedure Call;
end;

function ComplicatedCall: TComplicatedCallMaker;
begin
 { Fill default param values }
end;

procedure DoingSomeWorkHere;
begin
  with ComplicatedCall do begin
    Param7 := Value7;
    Param12 := Value12;
    Call;
  end;
end;

Это прекрасно работало до Delphi 2010. Очень полезный метод для выполнения вызовов, которые принимают загрузку параметров, но обычно нужны только два или три.Но никогда не те же самые.

И теперь это дает ... угадайте, что?

E2064: Left side cannot be assigned to.

Разве это полезное новое поведение нельзя как-то отключить?Любые идеи о том, как изменить шаблон, чтобы он работал?

Потому что серьезно, потерять такой удобный метод (и переписать кучу кода) без видимой причины ...

Ответы [ 2 ]

3 голосов
/ 01 июля 2011

Я нахожу немного удивительным, что это когда-либо работало, но так как вы говорите, что это сработало, я уверен, что вы правы. Я предполагаю, что изменение было сделано без учета методов записи. Без возможности вызывать методы эта конструкция была бы довольно бессмысленной.

Во всяком случае, компилятор не собирается снимать вас с этого, поэтому вам придется сделать следующее:

type
  TRecordType = record end;
  TComplicatedCallMaker = record
    Param1: TRecordType;
    procedure Call;
  end;

function ComplicatedCall: TComplicatedCallMaker;
begin
 { Fill default param values }
end;

procedure DoingSomeWorkHere(const Value: TRecordType);
var
  CallMaker: TComplicatedCallMaker;
begin
  CallMaker := ComplicatedCall;
  with CallMaker do begin
    Param1 := Value;
    Call;
  end;
end;
1 голос
/ 01 июля 2011

Я ... думаю, что я сделал это

Я надеюсь, что разработчики Delphi увидят, что они заставляют своих программистов делать!

type
  PCallMaker = ^TCallMaker;
  TCallMaker = record
    Param1: integer;
    Param2: integer;
    function This: PCallMaker; inline;
    procedure Call; inline;
  end;

function TCallMaker.This: PCallMaker;
begin
  Result := @Self;
 { Record functions HAVE to have correct self-pointer,
  or they wouldn’t be able to modify data. }
end;

procedure TCallMaker.Call;
begin
  writeln(Param1, ' ', Param2);
end;

function CallMaker: TCallMaker; inline
begin
  Result.Param1 := 0;
  Result.Param2 := 0;
end;

procedure DoingSomeWorkHere;
var cm: TCallMaker;
begin
 {Test the assumption that cm is consistent}
  cm := CallMaker;
  if cm.This <> @cm then
    raise Exception.Create('This wasn''t our lucky day.');

 {Make a call}
  with CallMaker.This^ do begin
    Param1 := 100;
    Param2 := 500;
    Call;
  end;
end;

Это работает, сохраняет все хорошие качества старой версии(скорость, простота, небольшие накладные расходы), но нет ли скрытых проблем с этим подходом?

...