Передайте параметр записи, не объявляя его сначала как переменную - PullRequest
20 голосов
/ 15 января 2012

Если я пытаюсь вызвать процедуру, которая имеет тип записи (не объект) в качестве параметра, возможно ли каким-то образом передать детали этого параметра "inline", не объявляя сначала переменную этого типа?

Например, предположим, у меня есть этот простой тип записи:

type TMyRecord = record
  AString: string;
  AnInt: Integer;
end;

и это объявление процедуры:

procedure MyProcedure(Rec: TMyRecord);

Если я хочу вызвать MyProcedure, нужно ли мне объявлять переменную типа TMyRecord или я могу сделать что-то вроде:

MyProcedure(TMyRecord("Test", 10));

Это не работает (XE2) (получите сообщение об ошибке компилятора, ожидающее ")".

Так, я могу сделать что-то подобное? Или не возможно.

Спасибо

Ответы [ 4 ]

17 голосов
/ 15 января 2012

Вопрос, который вы задаете, относится к читабельности кода, и существует решение, позволяющее избежать необходимости создания переменной.VCL использует это решение с записями TPoint и TRect.

Рассмотрим определение TPoint:

type
  TPoint = record
    X,Y integer
  end;

Чтобы передать TPoint в процедуру, которую вы могли быdo:

var
  MyPoint : TPoint;

begin
  MyPoint.X := 5;
  MyPoint.Y := 7;
  DoSomething( MyPoint );
end;

Это нормально, но занимает 3 строки, когда одна также возможна с использованием фабричной функции Point:

begin
  DoSomething( Point(5,7) );
end;

В Delphi функция была объявлена ​​следующим образом:

function Point( X, Y : integer ) : TPoint;
begin
  Result.X := X;
  Result.Y := Y;
end;

Затем вы можете вызвать эту функцию «inline» для создания записи «на лету», чтобы быстро. Вы увидите, что то же самое было предоставлено для TRect и т. Д. Я часто ставлю такиеЗаводская функция вместе с объявлением записи выглядит следующим образом, даже если я пока не планирую их использовать:

type
  TMyRecord = record
    A : integer;
    B : string;
  end;

function MyRecord( A : integer; const B : string ) : TMyRecord;
begin
  Result.A := A;
  Result.B := B;
end;

Использование этого метода может улучшить читаемость кода, а также гарантирует, что вы не случайноне указывать элемент записи.

17 голосов
/ 15 января 2012

Возможно использование структуры 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.

Рассматривая Delphi RTL, см. Определения типов записей TPoint и TRect в единицах system.types (XE2). Они определяют некоторые перегруженные конструкторы Create, которые используются во многих местах для предварительной инициализации структур записей в вызовах функций / процедур.

5 голосов
/ 16 января 2012

Просто получаю удовольствие от идеи Джона Исли:

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 параметры и назначать эти параметры локальной переменной записи.

3 голосов
/ 15 января 2012

Было бы неплохо!Но, нет.

Если передача данных в линию - это действительно ваша цель, то, возможно, вам подойдут параметры 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;

Вы также можете передать Arst of Const, который по сути являетсямассив TVarRec, который является вариантом записи, которая также включает информацию о типе как VType.Это забавная штука ..

Отличную статью можно найти на Delphi Corner Руди здесь: Delphi Corner Rudy, Параметры открытого массива

...