如何将数组值作为过程参数传递?

5

我假设我的问题可能已经存在于SO知识库中,只是我找不到它。如果是这种情况,请指导我找到原始问题,并投票将此问题关闭为重复问题。

这个问题与传递数组参数给过程有关。

以下情况简单直观且有效:

procedure MyProc(const A: array of ShortString);
begin
//
end

现在我可以调用MyProc并直接向它传递字符串:

MyProc(['no', 'trump', 'please']);

如果我声明一个ShortString类型的数组,会发生什么?

type
  TMyArray = array of ShortString;

procedure MyProc(const A: TMyArray);
begin
//
end

有没有一种方法可以直接传递数组类型的参数来执行MyProc?也就是说,使用与上面相同的过程调用。
+奖励问题:
type TMyRecord = record
  param, value: ShortString
end;

procedure MyProc(const R: TMyRecord);
begin
//
end

有没有一种技术可以调用过程并传递类型记录的值?类似于(伪代码):

MyProc((TMyRecord.param='aaa', TMyRecord.value='bbb'));

我提出这个问题的原因是:我不想声明一个变量并对其进行设置。相反,我希望直接将数组/记录值作为过程参数传递。


开放数组参数和动态数组有区别,尽管它们的语法非常相似。更多信息请参阅我的文章。如果要传递记录,只能通过声明一个创建记录的函数来实现。 - Rudy Velthuis
如果你需要调试这个程序,你会希望之前声明并设置了一个变量... - GuidoG
1
请一个问题一个问题地提问。还有,为什么你在使用短字符串? - David Heffernan
@David Heffernan,我使用Delphi 10.1 Berlin,它有一个已知问题(RSP-14914):如果你声明array of string,Code Insight就会停止工作。针对这个特定的例子,我使用了短字符串,这不会影响程序运行。 - Interface Unknown
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - David Heffernan
David,这只是一个例子 :) 在现实生活中,我总是坚持使用字符串。 - Interface Unknown
2个回答

5
正如其他人所说,它可以在Delphi XE7及更高版本中实现。在早期版本中,数组类型不能直接作为参数传递。
如果您无法没有这种“舒适”... 作为一种“丑陋”的解决方案,您可以使用一个中间函数,将动态数组复制到其相应的数组类型中:
function AsTypeArray(const MyArray : array of ShortString) : TMyArray;
begin
  SetLength(Result, Length(MyArray));
  Move(MyArray[Low(MyArray)], Result[0], Length(MyArray) * SizeOf(MyArray[Low(MyArray)]));
end;

所以你可以写成:

MyProc(AsTypeArray(['no', 'trump', 'please']));

我不喜欢这个解决方案,但如果您无法升级到Delphi XE7或更高版本,并且绝对想直接传递数组类型参数,我认为这是唯一的方法。
请注意,您可以将TMyArray对象作为参数传递给为接受动态数组而定义的函数:
procedure MyProc(const A: array of ShortString);
//...

var
  Arr : TMyArray;
begin
  //...
  MyProc(Arr); //It won't raise any error/warning
end;

同时,对于记录,需要一个返回记录类型的中间函数。

function MyRecord(Param : ShortString; Value : ShortString) : TMyRecord;
begin
  Result.Param := Param;
  Result.Value := Value;
end;

那么,您将能够在不声明变量的情况下通过您的记录。
MyProc(MyRecord('aaa', 'bbb'));

在最新版的Delphi中,我认为没有其他方法。

4

是的,您所写的内容在Delphi XE7及以上版本中可行。

program Project1;

{$APPTYPE CONSOLE}

type
  TMyArray = array of ShortString;

procedure MyProc(const A: TMyArray);
var
  s : ShortString;
begin
  for s in A do WriteLn(s);
end;

begin
  MyProc(['no', 'trump', 'please']);
  ReadLn;
end.

输出:


特朗普

XE7引入了新的动态数组初始化语法,允许像上面那样进行函数调用。在此之前,您需要使用显式构造函数进行初始化,如下所示:

 MyProc(TMyArray.Create('no', 'trump', 'please'));

记录一下,你需要一个构造函数或其他方法来返回记录类型。以下代码可行:

对于记录类型,您需要一个构造函数或其他方法来返回该类型。示例代码如下:

program Project1;

{$APPTYPE CONSOLE}

type
  TMyRecord = record
   param: ShortString;
   value: ShortString;
   constructor Create(AParam, AValue : ShortString);
  end;

constructor TMyRecord.Create(AParam: ShortString; AValue: ShortString);
begin
  param := AParam;
  value := AValue;
end;

procedure MyProc(const R: TMyRecord);
begin
  WriteLn(R.param);
  WriteLn(R.value);
end;

begin
  MyProc(TMyRecord.Create('foo', 'bar'));
  ReadLn;
end.

输出:

foo
bar


@smooty86 是的,当然。 - J...
真的吗?我不知道在最新的Delphi中如何工作,旧版本无法接受它...可以将动态数组作为开放数组参数传递,而不能反过来。 - smooty86
我明白了。我使用的是旧版本,在那个版本中它不会这样工作。 - smooty86
有一个替代方案。请看我的回答。 - Rudy Velthuis
我谈论数组的事情。在旧版本中,不可能将开放数组传递到动态数组参数中。 - smooty86
@smooty86 是的,在XE7之前是不可能的 - 你必须使用动态数组构造函数(就像我展示的那样)或传递一个正确类型的变量。 - J...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接