问题描述
我正在使用 Delphi 2007 (前通用),并且定义了许多函数,这些函数可用于所有 TObject
数组s后代,例如:
I'm using Delphi 2007 (Pre generics) and I've defined many functions who can be used for all arrays of TObject
's descendants, example:
function IndexOf(AArray : array of TObject; AItem : TObject) : integer;
begin
//...
end;
用于向它们传递 TObject
的动态数组s后代,我定义了一个数组类型 TObjectArray = TObject的数组
。这样,我可以强制转换动态数组并将其传递给函数,而不会出现任何问题:
For passing them dynamic arrays of TObject
's descendants, I've defined an array type TObjectArray = array of TObject
. In this way I can cast dynamic arrays and pass them to my functions without any problems:
type
TChild = class(TObject);
...
procedure Test();
var
Items : array of TChild;
Item : TChild;
begin
//...
IndexOf(TObjectArray(Items), Item);
end;
当我尝试传递开放数组参数时出现问题:
The problem comes when I try to pass them open array parameters:
procedure Test(AItems : array of TChild);
var
Item : TChild;
begin
//...
IndexOf(TObjectArray(AItems), Item);
end;
在这些情况下,编译器会引发以下错误消息:
In these cases, the compiler raises the following error message:
为什么会发生这种情况,如何避免这种情况?
Why does this happen and how can I avoid that?
推荐答案
在将ANY类型的数组传递给打开的数组参数时,只要元素相同,则无需进行类型转换。类型。您可以按原样传递数组,开放数组会接受它。这就是开放数组的全部要点。
You don't need to typecast when passing ANY type of array to an open array parameter, provided the elements are the same type. You can pass the array as-is, the open array will accept it just fine. That is the whole point of open arrays.
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;
但是,您不能传递 TChild
预期为 TObject
的数组。编译器将以不兼容的类型错误拒绝它。输入数组必须使用与打开数组相同的元素类型。
However, you cannot pass an array of TChild
where an array of TObject
is expected. The compiler will reject it with an "incompatible types" error. The input array must use the same element type as the open array.
简单的类型转换可以在传递动态数组或固定数组时解决此问题:
A simple typecast can fix that when passing a dynamic array or a fixed array:
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;
但是,您根本无法将打开的数组类型转换为任何其他数组类型。不同类型的数组具有不同的内存布局(将动态数组类型转换为另一个动态数组,或将固定数组类型转换为另一个固定数组,不会更改正在类型转换的数组的内存布局)。
But, you simply cannot typecast an open array to any other array type. Different types of arrays have different memory layouts (typecasting a dynamic array to another dynamic array, or a fixed array to another fixed array, does not change the memory layout of the array being typecasted).
在一个开放数组的情况下,它实际上根本不是一个数组,它只是指向所传递数组的第一个元素的指针,并且还有一个用于数组长度的第二个隐藏参数。换句话说,这种声明:
In the case of an open array, it is actually not even an array at all, it is just a pointer to the first element of the passed array, and there is a second hidden parameter for the array length. In other words, this kind of declaration:
procedure Test3(AItems : array of TChild);
实际上是由编译器在幕后实现的,如下所示:
Is actually implemented by the compiler behind the scenes like this:
procedure Test3(AItems : ^TChild; AItems_High: Integer);
因此,您必须将打开的数组元素复制到另一个数组,然后传递代替该数组:
So, you will have to make a copy of the open array elements to another array, and then pass that array along instead:
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;
这篇关于为什么将开放数组参数强制转换为数组类型会导致E2089无效类型转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!