Наши преимущества

Записать record в TObject

Ognev

ex-Team ITcluB
Команда форума
Credits
0
Всем доброго времени суток!

Извиняюсь, если тупой вопрос, но чего-то не осилил. Подскажите, как можно в TObject записать record и с ней потом работать. Пока не получилось даже что-то записать. В старом коде вместо record был class TCoverReliefPiar, и все работало (UserObject : TObject ):
NewGrid.UserObject := TCoverReliefPiar.Create;
Можно ли вместо класса засунуть туда запись?

UPD
Delphi XE10 Seatle.
 
Последнее редактирование модератором:
Там надо делать обертку классом, что лучше имхо

type
PMyRec = ^TMyRec;
TMyRec = record
I : integer;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
P : PMyRec;
begin
New(P);
P.I := 42;
ListBox1.AddItem('One',TObject(P));
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
I : integer;
begin
//Free memory
for I := 0 to ListBox1.Items.Count - 1 do
Dispose(PMyRec(ListBox1.Items.Objects));
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
P : PMyRec;
begin
P := PMyRec(ListBox1.Items.Objects[ ListBox1.ItemIndex ]);
ShowMessage( IntToStr(P.I) );
end;
 
Проблемы не увидел:

type
TCoverReliefPiar = record
Param: Integer;
end;

TNewGrid = class(...)
private
FUserObject: TCoverReliefPiar;
public
property UserObject: TCoverReliefPiar read FUserObject write FUserObject;
end;

...

var
NewGrid: TNewGrid;
CoverReliefPiar: TCoverReliefPiar;

...

CoverReliefPiar.Param := 1;
NewGrid.UserObject := CoverReliefPiar;

Если вопрос в этом:
NewGrid.UserObject.Param := 1;
то так - нельзя. Записи передаются по значению (в отличие от объектов классов) - следовательно, можно поменять только всё значение целиком (всю запись).

Но можно так:
type
TCoverReliefPiar = record
Param: Integer;
end;
PCoverReliefPiar = ^TCoverReliefPiar;

TNewGrid = class(...)
private
FUserObject: TCoverReliefPiar;
function GetUserObject: PCoverReliefPiar;
procedure SetUserObject(const AValue: PCoverReliefPiar);
public
property UserObject: PCoverReliefPiar read GetUserObject write SetUserObject;
end;

function TNewGrid.GetUserObject: PCoverReliefPiar;
begin
Result := @FUserObject;
end;

procedure TNewGrid.SetUserObject(const AValue: PCoverReliefPiar);
begin
Assert(Assigned(AValue));
FUserObject := AValue^;
end;

...

var
NewGrid: TNewGrid;

...

NewGrid.UserObject.Param := 1;

В этом случае свойство передаётся по указателю.

Если вопрос в этом:
type
TEmptyRecord = record
end;

TCoverReliefPiar = record
Param: Integer;
end;

TNewGrid = class(...)
private
FUserObject: TEmptyRecord;
public
property UserObject: TEmptyRecord read FUserObject write FUserObject;
end;

...

var
NewGrid: TNewGrid;
CoverReliefPiar: TCoverReliefPiar;

...

CoverReliefPiar.Param := 1;
NewGrid.UserObject := CoverReliefPiar;
то - нет, так нельзя. Передача по значению означает статический размер. Наследования в записях нет.

Можно, опять же, переделать всё на указатели, ввести первое поле, определяющее тип/размер записи (на манер dwSize в WinAPI). Но смысл это делать, если есть гораздо более удобные объекты/классы?
 
Последнее редактирование модератором:
Общее короткое резюме по этому вопросу именно что нужно делать обертку классом. И хранить запись в свойстве или поле - в зависимости от того, что требуется делать с записью и как. Иначе получается извращение.

Всем спасибо за ответы!
 
Сериализовать запись в JSON объект, с каких-то последних версий дельфи он вроде из коробки есть, и передавать как строку его удобнее, хоть по сети кидай, хоть между приложениями или окнами.
 
Верх