Пропустить параметр записи без объявления его сначала как переменной
Если я пытаюсь вызвать процедуру, которая имеет тип записи (не объект) в качестве параметра, возможно ли каким-то образом передать данные этого параметра "inline", не указав сначала первую переменную этого типа?
Например, предположим, что у меня есть этот простой тип записи:
type TMyRecord = record
AString: string;
AnInt: Integer;
end;
и объявление этой процедуры:
procedure MyProcedure(Rec: TMyRecord);
Если я хочу вызвать MyProcedure, мне нужно объявить переменную типа TMyRecord или я могу сделать что-то вроде:
MyProcedure(TMyRecord("Test", 10));
Это не работает (XE2) (получите ошибку компилятора об ожидании ")" ).
Итак, могу ли я сделать что-то подобное? Или невозможно.
Спасибо
Ответы
Ответ 1
Возможно использование структуры advanced record
.
Для получения дополнительной информации о advanced records
см. раздел Записи (расширенный) в справке Delphi.
Это небольшой прототип, чтобы увидеть, как он работает в вашем случае, чтобы предварительно инициализировать запись в вызове функции/процедуры:
Type
TRecord = record
AString : String;
AnInt : Integer;
Constructor Create( Const s : String; i : Integer);
end;
constructor TRecord.Create(const s: String; i: Integer);
begin
AString := s;
AnInt := i;
end;
procedure DoSomething( theRec : TRecord);
begin
WriteLn(theRec.AString, ' ',theRec.AnInt);
end;
begin
DoSomeThing( TRecord.Create('S',1));
ReadLn;
end.
Глядя на RTF Delphi, см. определения типов записей TPoint
и TRect
в модуле system.types
(XE2).
Они определяют некоторые перегруженные конструкторы Create
, которые используются во многих местах для предварительного инициализации структур записи в вызовах функций/процедур.
Ответ 2
Вопрос, который вы задаете, относится к читаемости кода, и есть решение, которое позволяет избежать необходимости создавать переменную. VCL использует это решение с записями TPoint
и TRect
.
Рассмотрим определение TPoint
:
type
TPoint = record
X,Y integer
end;
Чтобы передать TPoint
в процедуру, которую вы можете выполнить:
var
MyPoint : TPoint;
begin
MyPoint.X := 5;
MyPoint.Y := 7;
DoSomething( MyPoint );
end;
Это нормально, но занимает 3 строки, когда также возможно использование функции factory Point
:
begin
DoSomething( Point(5,7) );
end;
В Delphi функция объявлена следующим образом:
function Point( X, Y : integer ) : TPoint;
begin
Result.X := X;
Result.Y := Y;
end;
Затем вы можете вызвать эту функцию "inline", чтобы быстро создать запись "на лету"
Вы увидите то же, что и для TRect
и т.д. Я часто помещаю такую функцию factory вместе с объявлением записи следующим образом, даже если я еще не планирую их использовать:
type
TMyRecord = record
A : integer;
B : string;
end;
function MyRecord( A : integer; const B : string ) : TMyRecord;
begin
Result.A := A;
Result.B := B;
end;
Использование этого метода может улучшить читаемость кода, а также гарантирует, что вы случайно не опустили установку элемента записи.
Ответ 3
Просто развлекайтесь с идеей Джона Легли:
type TRec = record
X: string;
Y: Integer;
end;
procedure TestRec(const Rec: array of const);
var
R: TRec;
begin
R.X:= string(Rec[0].VUnicodeString);
R.Y:= Rec[1].VInteger;
ShowMessage(R.X + IntToStr(R.Y));
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
TestRec(['Test', 22]);
end;
В качестве параметров array of const
можно передать поля записей и назначить эти параметры локальной переменной записи.
Ответ 4
Было бы хорошо! Но, нет.
Если передача объектов inline действительно является вашей целью, возможно, вам понравятся параметры Open Array.
Procedure MyProcedure(const Vars: Array of Variant);
begin
ShowMessage(VarToStr(Vars[0])+' '+VarToStr(Vars[1]));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MyProcedure(['Test', 12]);
end;
Вы также можете передать массив Const, который в основном представляет собой массив TVarRec, который является вариантом записи, который также включает информацию о типе как VType. Это забавный материал.
Отличную статью можно найти на углу Руди Дельфа:
Rudy Delphi Corner, Параметры открытого массива