强制转换静态数组以打开不同元素类型的数组

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.

Dav*_*nan 3

这些演员阵容都相当丑陋。它们都可以工作,但是使用它们会让你感觉很脏。使用辅助函数是完全合理的:

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)

当然,如果您可以使用泛型,这会干净得多。