我正在维护并向Delphi XE2移植一堆非常旧的Delphi代码,这些代码充满了VarArrayCreate构造,伪造的动态数组的下限不为零。
使用Variant类型的缺点是:
var...
常量时,Variant系统开始进行不需要的转换或舍入)如果可以使用dynamic arrays,两者都可能没有实际意义。
变量数组的好处是它们可以具有非零下限。
我记得的是,动态数组总是以零的下限开始。
这仍然是真的吗?换句话说:是否可以让动态数组以不同于0的界限开始?
作为一个示例,针对特定情况的前/后示例(单维,但代码中包含多维数组,除了varDouble之外,代码还使用了各种其他varXXX
数据TVarData允许使用的类型:
function CalculateVector(aSV: TStrings): Variant;
var
I: Integer;
begin
Result := VarArrayCreate([1,aSV.Count-1],varDouble);
for I := 1 to aSV.Count-1 do
Result[I] := CalculateItem(aSV, I);
end;
CalculateItem
函数返回Double
。界限从1
到aSV.Count-1
。
当前替换是这样的,交换Result的空间第0个元素以改进编译时间检查:
type
TVector = array of Double;
function CalculateVector(aSV: TStrings): TVector;
var
I: Integer;
begin
SetLength(Result, aSV.Count); // lower bound is zero, we start at 1 so we ignore the zeroth element
for I := 1 to aSV.Count-1 do
Result[I] := CalculateItem(aSV, I);
end;
答案 0 :(得分:5)
答案 1 :(得分:2)
已经回答了您的直接问题,我还为您提供了可以在移植中使用的通用类的开头。
type
TSpecifiedBoundsArray<T> = class
private
FValues: TArray<T>;
FLow: Integer;
function GetHigh: Integer;
procedure SetHigh(Value: Integer);
function GetLength: Integer;
procedure SetLength(Value: Integer);
function GetItem(Index: Integer): T;
procedure SetItem(Index: Integer; const Value: T);
public
property Low: Integer read FLow write FLow;
property High: Integer read GetHigh write SetHigh;
property Length: Integer read GetLength write SetLength;
property Items[Index: Integer]: T read GetItem write SetItem; default;
end;
{ TSpecifiedBoundsArray<T> }
function TSpecifiedBoundsArray<T>.GetHigh: Integer;
begin
Result := FLow+System.High(FValues);
end;
procedure TSpecifiedBoundsArray<T>.SetHigh(Value: Integer);
begin
SetLength(FValues, 1+Value-FLow);
end;
function TSpecifiedBoundsArray<T>.GetLength: Integer;
begin
Result := System.Length(FValues);
end;
procedure TSpecifiedBoundsArray<T>.SetLength(Value: Integer);
begin
System.SetLength(FValues, Value);
end;
function TSpecifiedBoundsArray<T>.GetItem(Index: Integer): T;
begin
Result := FValues[Index-FLow];
end;
function TSpecifiedBoundsArray<T>.SetItem(Index: Integer; const Value: T);
begin
FValues[Index-FLow] := Value;
end;
我认为这很有效。我打算使用record
,但我认为这是不可行的。这归结为FLow
的值类型语义和FValues
的引用类型语义之间的混合。所以,我觉得这里的课程最好。
修改Low
时,它的行为也相当奇怪。
毫无疑问,你想延长这一点。您需要添加SetBounds
,副本,副本等等。但我认为你可能会发现它很有用。它肯定会显示如何使对象看起来非常像具有非零下限的数组。