0

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

function f(const x: array of const): String;

并以这种方式使用它:

f([1,3,4, "hello"]);

也可以将参数定义为“可变的”:

function g(var x: Byte): String;

var B: Byte;
g(B);

但是是否有可能定义一个函数,它可以接受任意数量的任何类型的参数并更改它们的所有值?我知道我可以使用指针来做到这一点,但是我不知道传递的参数的类型,所以弄乱它们是非常不安全的。


我只想创建一个函数,它可以返回多种不同类型的变量,而不仅仅是一种类型或只有 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]);
4

2 回答 2

2

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

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

  • 从一个开放的数组参数创建一个动态的 TValue 数组;
  • 将 TValue 的动态数组复制到一个新的动态数组,在途中修改各个值;
  • “就地”修改动态 TValues 数组中的项目。

享受。

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.
于 2012-11-07T21:11:34.957 回答
1
Procedure All(var a:Array of Variant);
var
 i:Integer;
begin
  for I := Low(a) to High(a) do
      begin

        if VarType(a[i])=258  then
          a[i] := a[i] + ' modified';

      end;
end;

Procedure AllConst( a:Array of Variant);
var
 i:Integer;
begin
  for I := Low(a) to High(a) do
      begin
        Showmessage(a[i]);
      end;
end;


procedure TForm3.Button1Click(Sender: TObject);
var
 a:Array of Variant;
begin
  AllConst([1,2,'Test']);
  SetLength(a,3);
  a[0] := 3.141;
  a[1] := 'Test';
  a[2] := 27;
  all(a);
  Showmessage(a[1]);
end;
于 2012-11-07T12:59:02.150 回答