Fab*_*zio 5 arrays delphi casting delphi-2007 open-array-parameters
我正在使用Delphi 2007(Pre generics),我已经定义了许多可以用于所有TObject
后代数组的函数,例如:
function IndexOf(AArray : array of TObject; AItem : TObject) : integer;
begin
//...
end;
Run Code Online (Sandbox Code Playgroud)
为了传递它们TObject
后代的动态数组,我已经定义了一个数组类型TObjectArray = array of TObject
.通过这种方式,我可以投射动态数组并将它们传递给我的函数而不会出现任何问题
type
TChild = class(TObject);
...
procedure Test();
var
Items : array of TChild;
Item : TChild;
begin
//...
IndexOf(TObjectArray(Items), Item);
end;
Run Code Online (Sandbox Code Playgroud)
当我尝试传递它们打开数组参数时出现问题:
procedure Test(AItems : array of TChild);
var
Item : TChild;
begin
//...
IndexOf(TObjectArray(AItems), Item);
end;
Run Code Online (Sandbox Code Playgroud)
在这些情况下,编译器会引发以下错误消息:
E2089无效的类型转换
为什么会发生这种情况,我该如何避免呢?
将ANY类型的数组传递给open数组参数时,如果元素的类型相同,则不需要进行类型转换.你可以按原样传递数组,open数组会接受它.这是开放阵列的重点.
type
TChild = class(TObject);
...
function IndexOf(AArray : array of TObject; AItem : TObject) : integer;
begin
//...
end;
procedure Test();
var
Items : array of TObject;
Item : TChild;
begin
//...
IndexOf(Items, Item);
end;
procedure Test2();
var
Items : array[0..N] of TObject;
Item : TChild;
begin
//...
IndexOf(Items, Item);
end;
procedure Test3(AItems : array of TObject);
var
Item : TChild;
begin
//...
IndexOf(AItems, Item);
end;
Run Code Online (Sandbox Code Playgroud)
但是,您无法传递数组TChild
所在的数组TObject
.编译器将使用"不兼容类型"错误拒绝它.输入数组必须使用与open数组相同的元素类型.
传递动态数组或固定数组时,简单的类型转换可以解决这个问题:
procedure Test();
type
TObjectArray = array of TObject;
var
Items : array of TChild;
Item : TChild;
begin
//...
IndexOf(TObjectArray(Items), Item);
end;
procedure Test2();
type
TObjectFixedArray = array[0..N] of TObject;
PObjectFixedArray = ^TObjectFixedArray;
var
Items : array[0..N] of TChild;
Item : TChild;
begin
//...
IndexOf(PObjectFixedArray(@Items)^, Item);
end;
Run Code Online (Sandbox Code Playgroud)
但是,您根本无法将打开的数组类型转换为任何其他数组类型.不同类型的数组具有不同的内存布局(将动态数组类型转换为另一个动态数组,或将固定数组转换为另一个固定数组,不会更改被类型化的数组的内存布局).
在开放数组的情况下,它实际上根本不是数组,它只是指向传递数组的第一个元素的指针,并且数组长度有第二个隐藏参数.换句话说,这种声明:
procedure Test3(AItems : array of TChild);
Run Code Online (Sandbox Code Playgroud)
实际上是由幕后编译器实现的,如下所示:
procedure Test3(AItems : ^TChild; AItems_High: Integer);
Run Code Online (Sandbox Code Playgroud)
因此,您必须将open数组元素的副本复制到另一个数组,然后传递该数组:
procedure Test3(AItems : array of TChild);
var
Items: array of TObject;
Item : TChild;
I: Integer;
begin
//...
SetLength(Items, Length(AItems));
For I := Low(AItems) to High(AItems) do
Items[I] := AItems[I];
IndexOf(Items, Item);
end;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
210 次 |
最近记录: |