Delphi 如何创建一个接受可变数量变量参数的函数?

Delphi 如何创建一个接受可变数量变量参数的函数?,delphi,Delphi,可以创建一个接受可变数量参数的函数: function f(const x: array of const): String; 并以这种方式使用它: f([1,3,4, "hello"]); 也可以将参数定义为“可变”: 但是,有没有可能定义一个函数,它可以接受任意数量的whatver类型的参数并更改它们的所有值? 我知道我可以使用指针来实现这一点,但是我不知道传递的参数的类型,所以处理它们是非常不安全的 我只想创建一个函数,它可以返回许多不同类型的变量数量,而不仅仅是1个类型或1个变量。

可以创建一个接受可变数量参数的函数:

function f(const x: array of const): String;
并以这种方式使用它:

f([1,3,4, "hello"]);
也可以将参数定义为“可变”:

但是,有没有可能定义一个函数,它可以接受任意数量的whatver类型的参数并更改它们的所有值? 我知道我可以使用指针来实现这一点,但是我不知道传递的参数的类型,所以处理它们是非常不安全的


我只想创建一个函数,它可以返回许多不同类型的变量数量,而不仅仅是1个类型或1个变量。我不想写无数行来使用这个函数——它应该是函数本身,在函数调用之前没有SetLength()或任何东西。这是迄今为止我做的最好的事情:

type TVarArr = Array of Variant;
     PVarArr = ^TVarArr;
Procedure f(a: PVarArr);
var
 i:Integer;
begin
  SetLength(A^, 4);
  a^[0] := 46;
end;

ar: TVarArr;
begin
f(@ar);
caption := IntToStr(ar[0]);

Tom将无法使用此答案,因为他的Delphi版本不够高,但D2010或更高版本的任何人都可以在此类挑战中很好地使用扩展rtti的TValue

以下是一个小型控制台应用程序,展示了如何:

  • 从开放数组参数创建TValue的动态数组
  • 将TValue的动态数组复制到一个新的动态数组中,同时修改各个值
  • “就地”修改动态tValue数组中的项
享受

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Rtti,
  System.SysUtils,
  System.TypInfo;

const
  StringKinds: set of TTypeKind = [tkChar, tkString, tkWChar, tkLString, tkWString, tkUString];

type
  TValueArray = array of TValue;

function ValueArrayFromConstArray(const aSource: array of TValue): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    Result[idx] := aSource[idx];
end;

function ReturnNewArray(const aSource: TValueArray): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    if aSource[idx].Kind in StringKinds then
      Result[idx] := 'Dest' + aSource[idx].ToString
    else
      if aSource[idx].Kind in [tkInteger] then
        Result[idx] := 10 + aSource[idx].AsInteger
      else
        Result[idx] := aSource[idx];
end;

procedure ModifyArrayValues(var aArray: TValueArray);
var
  idx: Integer;
begin
  for idx := Low(aArray) to High(aArray) do
    if aArray[idx].Kind in StringKinds then
      aArray[idx] := 'Dest' + aArray[idx].ToString
    else
      if aArray[idx].Kind in [tkInteger] then
        aArray[idx] := 10 + aArray[idx].AsInteger
      else
        ;//aArray[idx] := aArray[idx];
end;

var
  Source: TValueArray;
  Destination: TValueArray;
  Item: TValue;
  idx: Integer;
begin
  Source := ValueArrayFromConstArray(['Some', 42, TObject]);
  Destination := ReturnNewArray(Source);
  idx := 0;
  WriteLn('', #9, 'Old', #9, 'New');
  WriteLn('-', #9, '----', #9, '----');
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString, #9, Destination[idx].ToString);
    Inc(idx);
  end;
  WriteLn;
  WriteLn;
  WriteLn('', #9, 'Modified');
  WriteLn('-', #9, '----');
  Source := ValueArrayFromConstArray(['first', 50, TValue.From<TFloatValue>(fvCurrency)]);
  ModifyArrayValues(Source);
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString);
  end;
  ReadLn;
end.
程序项目1;
{$APPTYPE控制台}
{$R*.res}
使用
系统,Rtti,,
System.SysUtils,
System.TypInfo;
常数
StringKinds:TTypeKind的集合=[tkChar、tkString、tkWChar、tkLString、tkWString、tkUString];
类型
TValue数组=TValue的数组;
函数值数组fromcontarray(constasource:TValue的数组):TValue数组;
变量
idx:整数;
开始
设置长度(结果,长度(源));
对于idx:=低(aSource)到高(aSource)do
结果[idx]:=aSource[idx];
结束;
函数ReturnNewArray(const aSource:TValueArray):TValueArray;
变量
idx:整数;
开始
设置长度(结果,长度(源));
对于idx:=低(aSource)到高(aSource)do
如果源[idx].Kind为StringKinds,则
结果[idx]:='Dest'+aSource[idx].ToString
其他的
如果是源[idx].Kind in[tkInteger],则
结果[idx]:=10+A源[idx].A集成器
其他的
结果[idx]:=aSource[idx];
结束;
过程修改数组值(var aArray:TValueArray);
变量
idx:整数;
开始
对于idx:=低(aArray)到高(aArray)do
如果aArray[idx].Kind是StringKinds,那么
aArray[idx]:='Dest'+aArray[idx].ToString
其他的
如果aArray[idx].Kind in[tkInteger]则
aArray[idx]:=10+aArray[idx]。AsInteger
其他的
;//aArray[idx]:=aArray[idx];
结束;
变量
资料来源:TValueArray;
目的地:TValueArray;
项目:价值;
idx:整数;
开始
Source:=valueArrayFromConstantArray(['Some',42,TObject]);
目标:=ReturnNewArray(源);
idx:=0;
书面语(“,#9,'旧',#9,'新');
书面语(“-”,#9,“----”,#9,'----);
对于源do中的项目
开始
WriteLn(idx,#9,Item.ToString,#9,Destination[idx].ToString);
公司(idx),;
结束;
书面语;
书面语;
书面语(“,#9,'修改”);
WriteLn('-',#9'-');
来源:=ValueArrayFromConstary(['first',50,TValue.From(fvCurrency)]);
修改阵列值(来源);
对于源do中的项目
开始
书面文件(idx,#9,第.ToString项);
结束;
ReadLn;
结束。

Tom将无法使用此答案,因为他的Delphi版本不够高,但D2010或更高版本的任何人都可以在此类挑战中充分利用扩展rtti的TValue

以下是一个小型控制台应用程序,展示了如何:

  • 从开放数组参数创建TValue的动态数组
  • 将TValue的动态数组复制到一个新的动态数组中,同时修改各个值
  • “就地”修改动态tValue数组中的项
享受

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Rtti,
  System.SysUtils,
  System.TypInfo;

const
  StringKinds: set of TTypeKind = [tkChar, tkString, tkWChar, tkLString, tkWString, tkUString];

type
  TValueArray = array of TValue;

function ValueArrayFromConstArray(const aSource: array of TValue): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    Result[idx] := aSource[idx];
end;

function ReturnNewArray(const aSource: TValueArray): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    if aSource[idx].Kind in StringKinds then
      Result[idx] := 'Dest' + aSource[idx].ToString
    else
      if aSource[idx].Kind in [tkInteger] then
        Result[idx] := 10 + aSource[idx].AsInteger
      else
        Result[idx] := aSource[idx];
end;

procedure ModifyArrayValues(var aArray: TValueArray);
var
  idx: Integer;
begin
  for idx := Low(aArray) to High(aArray) do
    if aArray[idx].Kind in StringKinds then
      aArray[idx] := 'Dest' + aArray[idx].ToString
    else
      if aArray[idx].Kind in [tkInteger] then
        aArray[idx] := 10 + aArray[idx].AsInteger
      else
        ;//aArray[idx] := aArray[idx];
end;

var
  Source: TValueArray;
  Destination: TValueArray;
  Item: TValue;
  idx: Integer;
begin
  Source := ValueArrayFromConstArray(['Some', 42, TObject]);
  Destination := ReturnNewArray(Source);
  idx := 0;
  WriteLn('', #9, 'Old', #9, 'New');
  WriteLn('-', #9, '----', #9, '----');
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString, #9, Destination[idx].ToString);
    Inc(idx);
  end;
  WriteLn;
  WriteLn;
  WriteLn('', #9, 'Modified');
  WriteLn('-', #9, '----');
  Source := ValueArrayFromConstArray(['first', 50, TValue.From<TFloatValue>(fvCurrency)]);
  ModifyArrayValues(Source);
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString);
  end;
  ReadLn;
end.
程序项目1;
{$APPTYPE控制台}
{$R*.res}
使用
系统,Rtti,,
System.SysUtils,
System.TypInfo;
常数
StringKinds:TTypeKind的集合=[tkChar、tkString、tkWChar、tkLString、tkWString、tkUString];
类型
TValue数组=TValue的数组;
函数值数组fromcontarray(constasource:TValue的数组):TValue数组;
变量
idx:整数;
开始
设置长度(结果,长度(源));
对于idx:=低(aSource)到高(aSource)do
结果[idx]:=aSource[idx];
结束;
函数ReturnNewArray(const aSource:TValueArray):TValueArray;
变量
idx:整数;
开始
设置长度(结果,长度(源));
对于idx:=低(aSource)到高(aSource)do
如果源[idx].Kind为StringKinds,则
结果[idx]:='Dest'+aSource[idx].ToString
其他的
如果是源[idx].Kind in[tkInteger],则
结果[idx]:=10+A源[idx].A集成器
其他的
结果[idx]:=aSource[idx];
结束;
过程修改数组值(var aArray:TValueArray);
变量
idx:整数;
开始
对于idx:=低(aArray)到高(aArray)do
如果aArray[idx].Kind是StringKinds,那么
aArray[idx]:='Dest'+aArray[idx].ToString
其他的
如果aArray[idx].Kind in[tkInteger]则
aArray[idx]:=10+aArray[idx]。AsInteger
其他的
;//aArray[idx]:=aArray[idx];
结束;
变量
资料来源:TValueArray;
目的地:TValueArray;
项目:价值;
idx:整数;
开始
Source:=valueArrayFromConstantArray(['Some',42,TObject]);
目标:=ReturnNewArray(源);
idx:=0;
书面语(“,#9,'旧',#9,'新');
书面语(“-”,#9,“----”,#9,'----);
对于源do中的项目
开始
WriteLn(idx,#9,Item.ToString,#9,Destination[idx].ToString);
公司(idx),;
结束;
书面语;
书面语;
书面语(“,#9,'修改”);
WriteLn('-',#9'-');
来源:=ValueArrayFromConstary(['first',50,TValue.From(fvCurrency)]);
修改阵列值(来源);
对于源do中的项目
开始
书面文件(idx,#9,第.ToString项);
结束;
ReadLn;
结束。
函数f(变量x:常量数组):字符串如此处所述:@DavidHeffernan B
program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Rtti,
  System.SysUtils,
  System.TypInfo;

const
  StringKinds: set of TTypeKind = [tkChar, tkString, tkWChar, tkLString, tkWString, tkUString];

type
  TValueArray = array of TValue;

function ValueArrayFromConstArray(const aSource: array of TValue): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    Result[idx] := aSource[idx];
end;

function ReturnNewArray(const aSource: TValueArray): TValueArray;
var
  idx: Integer;
begin
  SetLength(Result, Length(aSource));
  for idx := Low(aSource) to High(aSource) do
    if aSource[idx].Kind in StringKinds then
      Result[idx] := 'Dest' + aSource[idx].ToString
    else
      if aSource[idx].Kind in [tkInteger] then
        Result[idx] := 10 + aSource[idx].AsInteger
      else
        Result[idx] := aSource[idx];
end;

procedure ModifyArrayValues(var aArray: TValueArray);
var
  idx: Integer;
begin
  for idx := Low(aArray) to High(aArray) do
    if aArray[idx].Kind in StringKinds then
      aArray[idx] := 'Dest' + aArray[idx].ToString
    else
      if aArray[idx].Kind in [tkInteger] then
        aArray[idx] := 10 + aArray[idx].AsInteger
      else
        ;//aArray[idx] := aArray[idx];
end;

var
  Source: TValueArray;
  Destination: TValueArray;
  Item: TValue;
  idx: Integer;
begin
  Source := ValueArrayFromConstArray(['Some', 42, TObject]);
  Destination := ReturnNewArray(Source);
  idx := 0;
  WriteLn('', #9, 'Old', #9, 'New');
  WriteLn('-', #9, '----', #9, '----');
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString, #9, Destination[idx].ToString);
    Inc(idx);
  end;
  WriteLn;
  WriteLn;
  WriteLn('', #9, 'Modified');
  WriteLn('-', #9, '----');
  Source := ValueArrayFromConstArray(['first', 50, TValue.From<TFloatValue>(fvCurrency)]);
  ModifyArrayValues(Source);
  for Item in Source do
  begin
    WriteLn(idx, #9, Item.ToString);
  end;
  ReadLn;
end.