用TArray <XXX>替换XXX数组是否安全

Ive*_*aev 13 arrays delphi generics dynamic-arrays delphi-xe5

我有很多变量声明为

var
  Something: array of XXX;
begin
  SetLength(Something, 10);
  try
    ...
  finally
    SetLength(Something, 0);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

将它们替换为安全的范围:

var
  Something: TArray<XXX>;
begin
  SetLength(Something, 10);
  try
    ...
  finally
    SetLength(Something, 0);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

小智 12

如前所述,TArray<XXX>与定义为的任何其他自定义类型完全相同array of XXX.实际上,TArray<XXX> 定义为的自定义类型array of XXX.

这就是说,被定义为一个自定义类型array of XXX等同于array of XXX在过程或函数参数的上下文.In procedure Foo(x: array of Integer),x是一个开放数组参数,可以接受任何类型的整数数组.相反,仅procedure Foo(x: TArray<Integer>)采用实际TArray<Integer>类型.尝试传递固定大小的数组时,以及尝试传递TDynIntegerArray(另一种类型,也定义为array of Integer)时,您可以看到差异.

因此,对于变量,如果有,请确保array of XXX将其更改为TArray<XXX>您想要的所有变量.只需确保您不进行全局搜索和替换.

  • @DavidHeffernan这只是因为`TArray <T>`恰好在第二方库可用的单元中定义(在你的例子中).它是通用的这一事实并不重要.两个第三方库同样可以添加对JCL的依赖,并使用`JclBase.TDynIntegerArray`.无论如何,这不是问题所在,我认为我们离得太远了. (2认同)

Dav*_*nan 5

这样做是完全安全的.编译器将生成相同的输出.

我个人会在其他条件相同的情况下建议这样做.通用阵列的使用TArray<T>为您提供了更大的灵活性和更好的类型兼容性.

当然,只有使用更实际的代码才能看到这些好处.您最常见的是使用通用容器时的好处.但是,在尝试使用多个不同的库构建代码时,您可能也会看到好处.

通用数组的使用允许简单的类型兼容性.在通用数组之前,您将定义一个这样的数组类型:

TIntArray = array of Integer;
Run Code Online (Sandbox Code Playgroud)

如果两个库执行此操作,则表示您具有不兼容的类型.如果库同意使用通用数组,那么将具有兼容性.

要更清楚地看到这一点,请考虑以下片段:

type
  TIntArray1 = array of Integer;
  TIntArray2 = array of Integer;
....
var
  arr1: TIntArray1;
  arr2: TIntArray2;
....
arr1 := arr2;
Run Code Online (Sandbox Code Playgroud)

此分配无效,并且因类型不匹配编译器错误而失败.这完全是在Pascal语言中预期的.它毕竟是强类型的,这些是不同的类型.即使它们的实现方式相同.

另一方面:

var
  arr1: TArray<Integer>;
  arr2: TArray<Integer>;
....
arr1 := arr2;
Run Code Online (Sandbox Code Playgroud)

是有效的,并编译.该泛型类型的兼容性文档说:

如果基类型相同(或者是常见类型的别名)并且类型参数相同,则两个实例化泛型被认为是赋值兼容的.

  • @MasonWheeler,确切地说!使用Datasnap使用的JSON编组可以完美地使用声明为`T`数组的字段类型,但是对于`TArray <T>`则失败.因此,往往答案是:它取决于. (2认同)
  • @StefanGlienke,如果TIntArray = Integer数组和TDynArray = TArray <Integer>使用TJSONConverters.GetJSONMarshaler.Marshal:XE5和XE6可以做得很好,我做了快速检查带有字段的对象,XE3不能. (2认同)