使用TArray<T>而不是Array of T的原因是什么?

35

我正在将一个老旧的Delphi应用程序迁移到Delphi-XE2,想知道是否有充分的理由将定义为Array of MyType的数组替换为TArray<MyType>。因此问题是使用TArray<T>Array of MyType相比,有哪些利弊?

3个回答

37
主要优点是更少的繁琐的类型标识规则。请考虑以下内容:
a: array of Integer;
b: array of Integer;

这两个变量不能互相赋值。如果写成以下形式,会导致编译错误:
a := b;

另一方面,如果您使用通用语法:

a: TArray<Integer>;
b: TArray<Integer>;

那么这两个变量就可以进行赋值操作。

当然,您也可以写成

type
  TIntegerArray = array of Integer;

但是所有参与者都需要同意使用相同的类型。如果所有代码都在您的控制之下,那么没有问题,但是当使用来自各种来源的代码时,通用动态数组的出现会产生巨大的差异。

另一个类似的优点是,您可以轻松地将通用数组类型作为通用方法的返回类型。

如果没有通用数组,您将被迫声明此类类型:

TArrayOfT = array of T

如果您的泛型类比较混乱,那么泛型数组可以解决这个问题。如果您正在非泛型类中编写一个泛型方法,则无法进行该声明。同样,泛型数组可以解决这个问题。

TMyClass = class
  class function Foo<T>: TArray<T>; static;
end;

这一切都遵循类型兼容性规则,就像文档中描述的那样:

类型兼容性

只有两个未实例化泛型类型相同或别名为一个公共类型时才被认为是可分配兼容的。

只有两个已实例化泛型类型的基础类型相同(或别名为一个公共类型)并且类型参数相同时才被认为是可分配兼容的。


2
泛型代码臃肿的问题怎么办?在XE2/XE3中解决了吗?我永远不会建议将变量声明为TArray<T>。 - kludg
7
@Serg:这个问题还没有解决,但它与此无关。问题在于方法被多次复制,但TArray<T>不是一个类,而是一个数组。因此没有需要复制的方法,也就没有代码膨胀的问题。 - Mason Wheeler
5
我很少看到使用TArray<T>,但这可能是因为Delphi开发人员仍然大多像1996年一样编写代码。忽略至少十年的新语法是一种保守的做法。(微笑) - Warren P
4
@Warren,我们的代码库完全使用它,原因在我的回答中有说明。在我看来,这是一个显而易见的选择。 - David Heffernan
5
在声明方法中的常量数组参数时,使用AMethod(const a : array of T);而不是AMethod(const a : TArray<T>);是一个重要方面。前者接受传递任何类型为T的数组,包括常量表达式,例如调用AMethod([1,2,3]);。而后者仅接受类型为TArray<T>的参数。 - LU RD
显示剩余16条评论

23
你可以使用一个构造函数来初始化 TArray<T> 中的值:
var
  LArray: TArray<Integer>;
begin
  LArray := TArray<Integer>.Create(1, 2, 3, 4);

对于 整数数组,你需要编写更多的代码:

var
  LArray: array of Integer;
begin
  SetLength(LArray, 4);
  LArray[0] := 1;
  LArray[1] := 2;
  LArray[2] := 3;
  LArray[3] := 4;

13
type TMyIntArr = array of integer; var LArray : TMyIntArr; LArray := TMyIntArr.Create(1,2,3,4); 运行正常。 - LU RD
5
@LURD: +1,这也适用于Delphi 2007以及支持泛型的后续版本(并且可以使用除整数以外的类型,以确保清楚明了)。 - Ken White
2
@EricGrange,你能举个例子吗?我在XE3中对通用数组创建和动态数组创建进行了反汇编,编译器生成的代码相同。在我看来没问题。 - LU RD
1
发布了一篇更详细的关于该主题的文章:http://delphitools.info/2013/02/18/delphi-array-constructors-performance-or-lack-of/ - Eric Grange
2
@Eric:从阅读你的文章来看,我认为应该在这里澄清一下,在某些速度关键的情况下使用Create array伪构造函数可能会导致性能下降。通过阅读上面的评论,我以为你是在说它有bug。不过,文章写得很好。 - jep
显示剩余4条评论

7

它对于函数结果非常有用。

例如:

在Delphi中,以下操作是不允许的。您需要在此处声明一个单独的类型。浪费时间啊。

function MyFunc:array of integer; 
begin
end;

等等,泛型来拯救:
function MyFunc:TArray<integer>;
begin
end;

8
好的,让我们公正地看待这个问题。TIntegerDynArray是在哪个版本引入的?D4?D6?因此,你应该使用一个自定义类型。 - Marco van de Voort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接