Uli*_*rdt 9 arrays delphi casting open-array-parameters
(我已经在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;
Run Code Online (Sandbox Code Playgroud)
调用有一些可能的变体DoSomethingWithControls:
变体1非常简单,但需要一个"适配器"类型,如TArray1
每个TLabel阵列的大小.我希望它更灵活.
变体2更灵活,更均匀但丑陋且容易出错.
Variant 3(由 TOndrej提供)类似于Variant 1 - 它不需要显式转换,但Variant 1提供了更多的编译器安全性,如果你弄乱了一些东西(例如,在复制粘贴时使数组边界错误).
我有没有想法如何制定这些调用没有这些缺点(不改变数组的元素类型)?它应该适用于D2007和XE6.
这些演员阵容都相当丑陋。它们都可以工作,但是使用它们会让你感觉很脏。使用辅助函数是完全合理的:
type
TControlArray = array of TControl;
function ControlArrayFromLabelArray(const Items: array of TLabel): TControlArray;
var
i: Integer;
begin
SetLength(Result, Length(Items));
for i := 0 to high(Items) do
Result[i] := Items[i];
end;
Run Code Online (Sandbox Code Playgroud)
然后你像这样调用你的函数:
DoSomethingWithControls(ControlArrayFromLabelArray(...));
Run Code Online (Sandbox Code Playgroud)
当然,如果您可以使用泛型,这会干净得多。