【发布时间】:2015-07-22 07:59:08
【问题描述】:
(我已经在 CodeReview 询问过这个问题,它在哪里被关闭为题外话。希望它在这里成为话题。)
我有一个派生类型的静态数组(如以下示例代码中的LabelsA: array[0..3] of TLabel;)和一个接受基本类型的开放数组(如procedure DoSomethingWithControls(const AControls: array of TControl);)的例程,我想调用DoSomethingWithControls那些静态数组。请看我的示例:
procedure DoSomethingWithControls(const AControls: array of TControl);
var
i: Integer;
begin
for i := Low(AControls) to High(AControls) do
Writeln(AControls[i].Name);
end;
procedure Test;
var
LabelsA: array[0..3] of TLabel;
LabelsB: array[0..1] of TLabel;
procedure Variant1;
type
TArray1 = array[Low(LabelsA)..High(LabelsA)] of TControl;
TArray2 = array[Low(LabelsB)..High(LabelsB)] of TControl;
begin
DoSomethingWithControls(TArray1(LabelsA));
DoSomethingWithControls(TArray2(LabelsB));
end;
procedure Variant2;
type
TControlArray = array[0..Pred(MaxInt div SizeOf(TControl))] of TControl;
PControlArray = ^TControlArray;
begin
DoSomethingWithControls(Slice(PControlArray(@LabelsA)^, Length(LabelsA)));
DoSomethingWithControls(Slice(PControlArray(@LabelsB)^, Length(LabelsB)));
end;
procedure Variant3;
var
ControlsA: array[Low(LabelsA)..High(LabelsA)] of TControl absolute LabelsA;
ControlsB: array[Low(LabelsB)..High(LabelsB)] of TControl absolute LabelsB;
begin
DoSomethingWithControls(ControlsA);
DoSomethingWithControls(ControlsB);
end;
begin
Variant1;
Variant2;
Variant3;
end;
调用DoSomethingWithControls有一些可能的变体:
变体 1 非常简单,但需要像
TArray1这样的“适配器”类型 对于每个大小的 TLabel 数组。我希望它更灵活。变体 2 更加灵活和统一,但丑陋且容易出错。
变体 3(由 TOndrej) 类似于 变体 1 - 它不需要显式转换,但变体 1 提供了 如果你搞砸了一些东西(例如 复制粘贴时数组边界出错)。
有什么想法可以在没有这些缺点的情况下制定这些调用(不改变数组的元素类型)?它应该适用于 D2007 和 XE6。
【问题讨论】:
-
为什么不使用 TObjectList
.ToArray? -
@whosrdaddy:对不起,忘了提到 D2007。 :-/
-
我很惊讶你不能只传递
TLabel的数组 -
@David:是的,我想这就是 co(ntra?)-variance 的事情。 :-)
-
@J... 当您将静态数组传递给开放数组参数时,编译器会传递长度信息
标签: arrays delphi casting open-array-parameters