Delphi 键入TArray是否安全<;X>;到X的数组?

Delphi 键入TArray是否安全<;X>;到X的数组?,delphi,generics,casting,delphi-xe2,dynamic-arrays,Delphi,Generics,Casting,Delphi Xe2,Dynamic Arrays,今天我发现了一个编译器bug() 以下程序无法编译: program Project1; {$APPTYPE CONSOLE} procedure P(M: TArray<TArray<Integer>>); begin SetLength(M, 1, 2); end; begin end. 我知道我可以这样解决它: procedure P(M: TArray<TArray<Integer>>); var i: Integer; be

今天我发现了一个编译器bug()

以下程序无法编译:

program Project1;
{$APPTYPE CONSOLE}

procedure P(M: TArray<TArray<Integer>>);
begin
  SetLength(M, 1, 2);
end;

begin
end.
我知道我可以这样解决它:

procedure P(M: TArray<TArray<Integer>>);
var
  i: Integer;
begin
  SetLength(M, 1);
  for i := low(M) to high(M) do
    SetLength(M[i], 2);
end;
程序P(M:TArray);
变量
i:整数;
开始
设定长度(M,1);
对于i:=低(M)到高(M)do
设定长度(M[i],2);
结束;
但我当然希望避免不得不求助于此

以下变体已编译并似乎有效:

procedure P(M: TArray<TArray<Integer>>);
type
  TArrayOfArrayOfInteger = array of array of Integer;
begin
  SetLength(TArrayOfArrayOfInteger(M), 1, 2);
end;
程序P(M:TArray);
类型
TarrayOfArrayOfFinteger=整数数组的数组;
开始
设定长度(TArrayOfArrayOfInteger(M),1,2);
结束;
我对动态数组、
TArray
casting、引用计数等的实现细节了解不够,因此无法确信这是安全的

是否有人知道这样或那样做是否会在运行时生成正确的代码?

通过泛型实现的设计,使用手动映射到整数数组的
将起作用

但是在这里使用泛型没有任何好处

仅代码:

type
  TArrayOfArrayOfInteger = array of array of Integer;

procedure P(M: TArrayOfArrayOfInteger);
begin
  SetLength(TArrayOfArrayOfInteger, 1, 2);
end;
还请注意,除非指定
const
var
,否则此类
TArray
数组将按值传递,并复制到堆栈上:

procedure P(var M: TArrayOfArrayOfInteger);
begin
  SetLength(TArrayOfArrayOfInteger, 1, 2);
end; // now caller instance of the parameter will be resized

var A: TArrayOfArrayOfInteger;
...
A := nil;
P(A);
assert(length(A)=1);
assert(length(A[0])=2);

编译器内部过程
SetLength
在堆栈上动态构造一个维度数组,并为任何动态数组调用
DynArraySetLength
,无论该数组是否通用。如果泛型数组在结构上与常规动态数组不兼容,则可能不会调用用于设置长度的相同实现


事实上,
DynArraySetLength
提供了
SetLength
作为多维数组的替代方案
DynArraySetLength
也可以用来代替typecast,但我看不出有任何理由选择其中一种动态数组> /COD>和 TARLY 实际上不同地被实现了(<代码> DyrimeReals是一个独立类,而 TARLY 是一个<代码> ToToStudio< /Cord>后代),这意味着T
数组和
TArray
在Delphi中也有一些实现差异。至少他们生产不同类型的RTTI。这是我的一些C++代码在Delphi编译器开始输出“<代码> TARLY 所以我希望一个硬类型转换可以工作。任何一个都会以“DynArraySetLength”(至少有一个是一维数组)结束,所以我同意上面的说法。@afrazier System.pas是特殊的,而且对于
TArray
,可能会有一些特殊的编译器魔法内在处理。这就是我所关心的。当然,他们不太可能实现一个新的不兼容的数组代码,而不是使用已经测试过的数组代码。@SertacAkyuz这是非常有力的证据。你能详细解释一下吗?这个错误在XE4中被修复了。你有任何文档来支持“按设计”断言吗?在这里使用泛型有一个好处。在通用容器类中,我可以编写如下函数:
函数ToArray:TArray
。显然,如果不使用通用的
TArray
,我就无法做到这一点。我知道var和const的所有内容。我的例子显然毫无用处,毫无意义。它被设计成一个尽可能小的例子来说明这个错误。鉴于代码无法运行,担心运行时性能似乎毫无意义。@David使用泛型,您可以将类似函数的函数声明为array:array of T并使用嵌套类型,这样您甚至可以命名它。@Arioch否,该代码不可编译。没有必要给塔瑞起名字。它已经有名字了。一个名字就够了。@David,是的,它已经有一个名字了,名字是“T数组”;-)我不明白为什么要保护声明数组的两种方法的分离。特别是对于这种隔离,只有70年代的“Pascal Report”才有支持,它已经被大多数其他类型(如集合和范围)颠覆了。@Arioch这就是你的名字。使用该名称意味着您的代码将无法编译。这主意真没用。你提出的改变是明智的,但我认为在Emba实施之前,地狱将会冻结。我可能错了,但我认为少量RTL更改更有可能发生。@David-不客气!无论如何,我仍然希望有人提出一个更具体的说法。我根本不知道Emba的C++。恩巴C++中的<代码>动态数组> />代码>和代码> TARLY < /C> >它们是如何与Delphi相关的?它们是直接与Delphi的<>代码>…>代码> >代码> TARLY < /C> >类型的模板类,非常类似于<代码> ANSICONS/<代码>,
UnicodeString
Variant
类直接对应于它们的Delphi对应类。它们都是C++类,允许C++和Delphi相互交换数据,然后是“左手不理会右手的行为”的另一个例子。在delphi中,类型TArray=定义为T的数组。它不像TList那样是类。C++与Delphi又一次不同,但是 TARLY 是通用的,所以我确信也会涉及到这些问题。我猜正因为如此,
TArray
字节数组
实际上是不同的。他们确实解释了为什么他们有不同的RTTI。
procedure P(var M: TArrayOfArrayOfInteger);
begin
  SetLength(TArrayOfArrayOfInteger, 1, 2);
end; // now caller instance of the parameter will be resized

var A: TArrayOfArrayOfInteger;
...
A := nil;
P(A);
assert(length(A)=1);
assert(length(A[0])=2);