传递记录参数而不首先将其声明为变量

Jas*_*son 23 delphi delphi-xe2

如果我试图调用一个记录类型(不是对象)作为参数的过程,是否有可能以某种方式传递该参数"inline"的细节而不必先声明该类型的变量?

假设我有这种简单的记录类型:

type TMyRecord = record
  AString: string;
  AnInt: Integer;
end;
Run Code Online (Sandbox Code Playgroud)

和这个程序声明:

procedure MyProcedure(Rec: TMyRecord);
Run Code Online (Sandbox Code Playgroud)

如果我想调用MyProcedure,我必须声明TMyRecord类型的变量,或者我可以执行以下操作:

MyProcedure(TMyRecord("Test", 10));
Run Code Online (Sandbox Code Playgroud)

这不起作用(XE2)(得到关于它的编译器错误,期望")").

那么,我可以这样做吗?或者不可能.

谢谢

LU *_* RD 18

可以使用该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.
Run Code Online (Sandbox Code Playgroud)

查看Delphi RTL,请参阅记录类型TPointTRect单位system.types(XE2)的定义.它们定义了一些重载的Create构造函数,这些构造函数在很多地方用于预处理函数/过程调用中的记录结构.


Bri*_*ost 17

您要问的问题与代码可读性有关,并且有一个避免必须创建变量的解决方案.VCL使用此解决方案与记录TPointTRect.

考虑以下定义TPoint:

type
  TPoint = record
    X,Y integer
  end;
Run Code Online (Sandbox Code Playgroud)

要传递TPoint给您可能执行的过程:

var
  MyPoint : TPoint;

begin
  MyPoint.X := 5;
  MyPoint.Y := 7;
  DoSomething( MyPoint );
end;
Run Code Online (Sandbox Code Playgroud)

这很好但是当使用工厂功能时也可以使用3行Point:

begin
  DoSomething( Point(5,7) );
end;
Run Code Online (Sandbox Code Playgroud)

在Delphi中,函数声明如下:

function Point( X, Y : integer ) : TPoint;
begin
  Result.X := X;
  Result.Y := Y;
end;
Run Code Online (Sandbox Code Playgroud)

然后你可以调用这个函数'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;
Run Code Online (Sandbox Code Playgroud)

使用此技术可以提高代码的可读性,还可以确保您不会意外地省略设置记录元素.

  • 我认为_does_回答了这个问题("那么,我可以这样做吗?" - Brian Frost提供了一种方法来做类似的事:)) (5认同)
  • +1.我认为这就是OP正在寻找的东西. (4认同)
  • @KenWhite:一个单独的函数`MyRect`,这样你就可以避免在你想要传递几个值的地方声明一个var,对我来说似乎不是"很多代码".在其他地方声明类型在这个解决方案中完全没有实际意义. (2认同)

klu*_*udg 5

只是玩约翰伊斯利的想法:

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;
Run Code Online (Sandbox Code Playgroud)

可以将记录字段作为array of const参数传递,并将这些参数分配给本地记录变量.

  • -1。它不必要地复杂。用两个参数声明该功能,每个字段一个。给他们具体的类型。从通话现场卸下支架。 (2认同)
  • @RobKennedy - 你的建议很乏味.编程应该很有趣.:) (2认同)