动态数组长度的32位和64位不同类型?

时间:2017-08-02 09:09:39

标签: delphi delphi-10.1-berlin

我有一个在Win32上正常运行的DUnitX测试套件。但是当我尝试为Win64编译它时,这一行会产生编译错误:

Assert.AreEqual(4, Length(r.Values));

[dcc64错误] ...:E2532无法从方法&#39; AreEqual&#39; <的不同参数类型推断泛型类型参数/ p>

r.Values定义为:

Type TIntegers = TArray<Integer>

Assert.AreEqual有不同的重载实现,dcc64无法选择正确的...好的,但为什么呢?为什么dcc32可以毫无问题地编译它?

我唯一的线索是,如果我用鼠标悬停,Delphi会告诉我Length的类型是System.Smallint。使用Smallint参数没有Assert.AreEqual实现......果然,如果我将它转换为Integer,dcc64将编译它。

但这让我烦恼不已。如果我查看System.pas单元,我可以看到DynArraySetLength采用NativeInt参数...一个64位整数(我希望无符号,但不确定)。那么为什么Length会返回一个16位有符号整数?那似乎等待发生麻烦,对吗?

我错过了什么?

1 个答案:

答案 0 :(得分:9)

在64位中,TArray的长度为Int64。据我所知,AreEqual没有Int64重载,因此它尝试使用通用版本:AreEqual<>。但看起来,从参数来看,它无法决定哪一个。

所以在Win64中,请执行:

 Assert.AreEqual<Int64>(4, Length(r.Values));

 Assert.AreEqual(4, Integer(Length(r.Values)));

后者当然是最简单的,因为它应该在Win32和Win64中工作,但可能无法处理非常大的数组。

FWIW,Length不会返回Smallint。但是对于平台之间不同的函数,尤其是像Length这样的“编译器魔术”函数,可能会发生这种(错误的)信息。这是IDE的问题,而不是编译器。

更新

正如@RemyLebeau所说,使用NativeInt代替可能更容易。这应该适用于Win32和Win64,因为NativeInt在Win32中是Int32,在Win64中是Int64,它也是_DynArrayLength返回的内容:

Assert.AreEqual<NativeInt>(4, Length(r.Values));