Delphi SetLength自定义索引

Delphi SetLength自定义索引,delphi,arrays,indexing,dynamic-arrays,Delphi,Arrays,Indexing,Dynamic Arrays,在Delphi中,可以创建以下类型的数组 var Arr: array[2..N] of MyType; 这是一个由N-1元素组成的数组,索引范围从2到N 如果我们改为声明一个动态数组 var Arr: array of MyType 然后通过 SetLength(Arr, N - 1) 然后这些元素将从0索引到N-2。是否可以将它们从2索引到N(比如说)?否,在Delphi中,动态数组总是从零索引。唯一可以模仿这种行为的方法是使用指针 type TMyTypeArr = ar

在Delphi中,可以创建以下类型的数组

var
  Arr: array[2..N] of MyType;
这是一个由
N-1
元素组成的数组,索引范围从2到N

如果我们改为声明一个动态数组

var
  Arr: array of MyType
然后通过

SetLength(Arr, N - 1)

然后这些元素将从0索引到N-2。是否可以将它们从2索引到N(比如说)?

否,在Delphi中,动态数组总是从零索引。

唯一可以模仿这种行为的方法是使用指针

type
  TMyTypeArr = array [ 0..High(Integer) div sizeof( MyType ) - 1 ] of Mytype;
  PMyTypeArr = ^TMyTypeArr;
var
  x: ;
  A: PMyTypeArr;
begin
  SetLength( A, 2 );
  x := PMyTypeArr( @A[ 0 ] ); Dec( PMyType( x ), 2 ); // now [2,4> is valid.
  x[2] := Get_A_MyType();
end;  

请注意,您丢失了任何范围检查,将其与非零起始阵列结合使用是一个非常糟糕的主意

如果您真的需要这个索引,那么您可以编写一个简单的“translation”函数,它将接收一个从2到N范围内的索引数字,并返回一个从0到N-2的索引,只需从参数中减去2即可,例如:

function translate(i : integer) : integer;
begin
  result := i - 2;
end;
您可以这样调用数组:

array[translate(2)]
function XYZ(i : integer) : MyType;
begin
  // Do range checking here...
  result := MyArray[i - 2];
end;
当然,您还可以在函数中执行范围检查,也许您可以给它一个较短的名称

或者更好的方法是,使用如下函数包装对阵列的整个访问:

array[translate(2)]
function XYZ(i : integer) : MyType;
begin
  // Do range checking here...
  result := MyArray[i - 2];
end;

希望这有帮助是的通过使用技巧
首先声明一个新类型。我使用记录类型而不是类,因为记录更容易使用

type
  TMyArray = record
  strict private
    FArray: array of Integer;
    FMin, FMax:Integer;
    function GetItem(Index: Integer): Integer;
    procedure SetItem(Index: Integer; const Value: Integer);
  public
    constructor Create(Min, Max: integer);
    property Item[Index: Integer]: Integer read GetItem write SetItem; Default;
    property Min: Integer read FMin;
    property Max: Integer read FMax;
  end;
定义了recordtype之后,您现在需要实现一些代码:

constructor TMyArray.Create(Min, Max: integer);
begin
  FMin := Min;
  FMax := Max;
  SetLength(FArray, Max + 1 - Min);
end;

function TMyArray.GetItem(Index: Integer): Integer;
begin
  Result := FArray[Index - FMin];
end;

procedure TMyArray.SetItem(Index: Integer; const Value: Integer);
begin
  FArray[Index - FMin] := Value;
end;
声明了类型后,现在可以开始使用它:

var
  Arr: TMyArray;
begin
  Arr := TMyArray.Create(2, 10);
  Arr[2] := 10;
创建具有特定范围的数组实际上是一个简单的技巧,如果您愿意,可以使其更加灵活。或者将其转换为类。就我个人而言,我更喜欢这些简单类型的唱片