这似乎是一个奇怪的请求,但有一个很好的理由(代码生成应用程序)。我将变量数组传递给包含在变量数组中的过程,如下所示:
TVarArray = array of variant;
procedure TMainForm.Button1Click(Sender: TObject);
var
params: TVarArray;
numRows: integer;
numCols: integer;
i: integer;
j: integer;
begin
SetLength(params, 2);
numRows := 2;
numCols := 2;
params[0] := 5;
params[1] := VarArrayCreate([1, numRows, 1, numCols], varVariant);
for i := 1 to numRows do
for j := 1 to numCols do
params[1][i, j] := i + j;
TestProc(params);
end;
procedure TMainForm.TestProc(params: TVarArray);
var
arr: variant;
p: PVariant;
v: variant;
begin
arr := params[1]; // -- Copies the array to arr.
arr[2, 2] := 99;
p := @(params[1]);
p^[2, 2] := 88; // -- Directly reference the passed-in array.
v := p^; // -- Copies the array to v -> How to prevent?
v[2, 2] := 77; // -- This should change the value in the original array.
edit1.Text := VarToStr(arr[2, 2]); // -- 99
edit2.Text := VarToStr(params[1][2, 2]); // -- 88 - should be 77
edit3.Text := VarToStr(v[2, 2]); // -- 77
end;
我不想创建数组的副本,因此可以使用p ^ []直接访问传入的数组。但是,我不想在TestProc中使用p ^语法,但更喜欢使用不带^的变量名。当然,如果我尝试v:= p ^我只是得到一份副本。有没有办法解决?谢谢!
答案 0 :(得分:3)
您正在寻找的是一个局部变量,它可以充当其他东西的引用(特别是Variant
数组中的元素)。但是,Delphi无法创建“本地引用”变量。引用仅存在于以var
,out
或有时const
传递的参数的上下文中。
也许您可以引入子例程并将param[1]
作为var
参数传递。在子例程中,您可以引用该参数,它会将数组元素作为调用者的别名。例如:
procedure ModifyVariant(var p: Variant);
begin
p[2, 2] := 77;
end;
procedure TMainForm.TestProc(params: TVarArray);
var
p: PVariant;
begin
p := @params[1];
ModifyVariant(params[1]);
Assert(params[1][2, 2] = p^[2, 2]);
end;
ModifyVariant
甚至可以是一个匿名过程,因此您可以在与调用者相同的范围内实现:
procedure TMainForm.TestProc(params: TVarArray);
var
ModifyVariant: reference to procedure(var x: Variant);
p: PVariant;
begin
p := @params[1];
ModifyVariant := procedure(var v: Variant)
begin
v[2, 2] := 77;
end;
ModifyVariant(params[1]);
Assert(params[1][2, 2] = p^[2, 2]);
end;
但是,这些看起来都不是特别吸引人,特别是如果你害怕仅仅指针访问会“吓跑”代码的消费者。
您已经提到过,您希望您的用户将自己的代码合并到您正在生成的代码中。我不建议这样做。毕竟,他们重新运行代码生成器后他们应该做些什么呢?他们肯定会失去他们所做的任何定制。最好将生成的代码保持分离,最好是在单独的文件中。对于用户自定义,您可以以用户可以实现的回调函数的形式提供挂钩。这样,例如,用户可以提供与ModifyVariant
类似的内容,然后您生成的代码可以简单地调用它。您将拥有“变体引用”,并且您将生成与用户代码完全分离的代码。