gpt4 book ai didi

arrays - 为什么将开放数组参数转换为数组类型会导致 E2089 无效类型转换?

转载 作者:行者123 更新时间:2023-12-03 14:59:16 25 4
gpt4 key购买 nike

我正在使用Delphi 2007(Pre generics),并且我定义了许多可用于TObject后代数组的函数,例如:

function IndexOf(AArray : array of TObject; AItem : TObject) : integer;
begin
//...
end;

为了向它们传递 TObject 后代的动态数组,我定义了一个数组类型 TObjectArray = array of TObject。通过这种方式,我可以转换动态数组并将它们传递给我的函数,没有任何问题:

type
TChild = class(TObject);

...

procedure Test();
var
Items : array of TChild;
Item : TChild;
begin
//...
IndexOf(TObjectArray(Items), Item);
end;

当我尝试向它们传递开放数组参数时,问题就出现了:

procedure  Test(AItems : array of TChild);
var
Item : TChild;
begin
//...
IndexOf(TObjectArray(AItems), Item);
end;

在这些情况下,编译器会引发以下错误消息:

E2089 Invalid typecast

为什么会发生这种情况以及如何避免这种情况?

最佳答案

将任何类型的数组传递给开放数组参数时,只要元素类型相同,就不需要进行类型转换。您可以按原样传递数组,开放数组将很好地接受它。这就是开放数组的全部意义。

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;

但是,您不能在需要 TObject 数组的地方传递 TChild 数组。编译器将拒绝它并显示“不兼容类型”错误。输入数组必须使用与开放数组相同的元素类型。

传递动态数组或固定数组时,简单的类型转换可以解决此问题:

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;

但是,您根本无法将开放数组类型转换为任何其他数组类型。不同类型的数组具有不同的内存布局(将动态数组类型转换为另一个动态数组,或将固定数组转换为另一个固定数组,不会更改正在类型转换的数组的内存布局)。

在开放数组的情况下,它实际上根本不是数组,它只是指向传递数组的第一个元素的指针,并且还有第二个隐藏参数用于数组长度。换句话说,这种声明:

procedure Test3(AItems : array of TChild);

实际上是由编译器在幕后实现的,如下所示:

procedure Test3(AItems : ^TChild; AItems_High: Integer);

因此,您必须将打开的数组元素复制到另一个数组,然后传递该数组:

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;

关于arrays - 为什么将开放数组参数转换为数组类型会导致 E2089 无效类型转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50414260/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com