«Левая сторона не может быть назначена» для свойств типа записи в Delphi

В самих словарях нет упорядоченных элементов как таковых, если вы хотите напечатать их и т. д. в некотором порядке, вот несколько примеров:

В Python 2.4 и выше:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

for key in sorted(mydict):
    print "%s: %s" % (key, mydict[key])

дает:

alan: 2
bob: 1
carl: 40
danny: 3

(Python ниже 2.4:)

keylist = mydict.keys()
keylist.sort()
for key in keylist:
    print "%s: %s" % (key, mydict[key])

Источник: http://www.saltycrane.com/blog/2007/09 / как к своему роду-питон-словарь по-ключам /

20
задан Kromster 30 November 2018 в 06:30
поделиться

5 ответов

Так как "Rec" является свойством, компилятор рассматривает его немного по-другому, потому что он должен сначала оценить "чтение" свойства decl. Рассмотрите это, которое семантически эквивалентно Вашему примеру:

...
property Rec: TRec read GetRec write FRec;
...

при рассмотрении его как это Вы видите, что первая ссылка на "Rec" (перед точкой '.'), должен назвать GetRec, который создаст временную локальную копию Rec. Эти временные файлы дизайном, "только для чтения". Это - то, с чем Вы сталкиваетесь.

Другая вещь, которую можно сделать здесь, состоит в том, чтобы вспыхнуть отдельные поля записи как свойства на содержании класса:

...
property RecField: Integer read FRec.A write FRec.A;
...

Это позволит Вам непосредственно присваиваться через свойство к полю той встроенной записи в экземпляре класса.

35
ответ дан Allen Bauer 30 November 2018 в 06:30
поделиться

Как другие сказали - свойство чтения возвратит копию записи, таким образом, присвоение полей не будет действовать на копию, принадлежавшую TForm1.

Другая опция - что-то как:

  TRec = record
    A : integer;
    B : string;
  end;
  PRec = ^TRec;

  TForm1 = class(TForm)
  private
    FRec : PRec;
  public
    constructor Create;
    destructor Destroy; override;

    procedure DoSomething(ARec: TRec);
    property Rec : PRec read FRec; 
  end;

constructor TForm1.Create;
begin
  inherited;
  FRec := AllocMem(sizeof(TRec));
end;

destructor TForm1.Destroy;
begin
  FreeMem(FRec);

  inherited;
end;

Delphi разыменует указатель PRec для Вас, таким образом, вещи как это будут все еще работать:

Form1.Rec.A := 1234; 

нет никакой потребности в части записи свойства, если Вы не хотите подкачать буфер PRec это точки FRec в. Я действительно не предложил бы сделать такой свопинг через свойство так или иначе.

2
ответ дан otherchirps 30 November 2018 в 06:30
поделиться

Да это - проблема. Но проблема может быть решена с помощью рекордных свойств:

type
  TRec = record
  private
    FA : integer;
    FB : string;
    procedure SetA(const Value: Integer);
    procedure SetB(const Value: string);
  public
    property A: Integer read FA write SetA;
    property B: string read FB write SetB;
  end;

procedure TRec.SetA(const Value: Integer);
begin
  FA := Value;
end;

procedure TRec.SetB(const Value: string);
begin
  FB := Value;
end;

TForm1 = class(TForm)
  Button1: TButton;
  procedure Button1Click(Sender: TObject);
private
  FRec : TRec;
public
  property Rec : TRec read FRec write FRec;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Rec.A := 21;
  Rec.B := 'Hi';
end;

Это компилирует и работает без проблемы.

20
ответ дан Kromster 30 November 2018 в 06:30
поделиться

Компилятор мешает Вам присвоить временному файлу. Эквивалент в C# разрешен, но он не имеет никакого эффекта; возвращаемое значение свойства Rec является копией базового поля, и присваивающий полю на копии NOP

7
ответ дан Barry Kelly 30 November 2018 в 06:30
поделиться

Поскольку у Вас есть неявный метод get и функции метода set, и Вы не можете изменить Результат функции, поскольку это - параметр константы.

(Примечание: В случае, если Вы преобразовываете запись в объект, результатом на самом деле был бы указатель, таким образом эквивалентный параметру var).

, Если Вы хотите остаться с Записью, необходимо использовать промежуточную переменную (или Полевую переменную) или использовать оператор WITH.

Посмотрите различные поведения в следующем коде с явным методом get и функциями метода set:

type
  TRec = record
    A: Integer;
    B: string;
  end;

  TForm2 = class(TForm)
  private
    FRec : TRec;
    FRec2: TRec;
    procedure SetRec2(const Value: TRec);
    function GetRec2: TRec;
  public
    procedure DoSomething(ARec: TRec);
    property Rec: TRec read FRec write FRec;
    property Rec2: TRec  read GetRec2 write SetRec2;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.DoSomething(ARec: TRec);
var
  LocalRec: TRec;
begin
  // copy in a local variable
  LocalRec := Rec2;
  LocalRec.A := Arec.A; // works

  // try to modify the Result of a function (a const) => NOT ALLOWED
  Rec2.A := Arec.A; // compiler refused!

  with Rec do
    A := ARec.A; // works with original property and with!
end;

function TForm2.GetRec2: TRec;
begin
  Result:=FRec2;
end;

procedure TForm2.SetRec2(const Value: TRec);
begin
  FRec2 := Value;
end;
4
ответ дан François 30 November 2018 в 06:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: