今天我尝试在XE4中编译我的XE3项目。我面临的第一个问题是使用Indy的FTCPClient.Socket.ReadBytes()方法。
在接受TBytes类型之前,现在它坚持使用TidBytes。
说明: TIdBytes =字节数组; TBytes,我不确定我猜它是类似于TArray的泛型,它是字节数组。
问题1: 为什么编译器抱怨说'[dcc32 Error] HistoricalStockData.pas(298):E2033实际和正式var参数的类型必须相同'。我认为它们已经相同了。
问题2: 我应该用每个新的delphi版本修改我的源代码吗?
感谢。
答案 0 :(得分:8)
早期Indy 10版本中TIdBytes
是TBytes
的简单别名的原因主要是为了与使用SysUtils.TEncoding
的{{1}}兼容。 Indy的TBytes
类型曾是D2009 +中TIdTextEncoding
的简单别名,因此SysUtils.TEncoding
必须是TIdBytes
匹配的简单别名。
然而,TBytes
在XE3中为Indy造成了相当大的麻烦,主要是因为泛型的RTTI问题(TBytes
是最近Delphi版本中TBytes
的一个简单别名)。因此,Indy 10.6重新设计了TArray<Byte>
以完全不再依赖TIdTextEncoding
(还有其他原因),然后允许SysUtils.TEncoding
更改为自己的数组键入以避免XE3问题向前发展。
另一方面,你传递了一个TIdBytes
,其中TBytes
是预期的,所以你的编程就是因为你没有首先关注Indy的定义界面。 Indy 10的所有基于字节的操作(包括TIdBytes
)始终仅在ReadBytes()
上运行。 TIdBytes
静默映射到TIdBytes
的事实是您不应该在代码中依赖的实现细节。 Indy 10需要TBytes
,所以使用TIdBytes
,那么你就不会有关于不兼容类型的编译器错误。
答案 1 :(得分:3)
以下两个声明不相同,即使它们看起来像是。它们不是assignment compatible,即使它们都基于array of string
。
type
TStringArrayOne = array of string;
TStringArrayTwo = array of string;
var
AVar1, AVar2: TStringArrayOne;
AVar3, AVar4: TStringArrayTwo;
begin
AVar1 := TStringArrayOne.Create('a', 'b', 'c'); // Compiles
AVar2 := TStringArrayTwo.Create('a', 'b', 'c'); // Won't compile
AVar3 := TStringArrayTwo.Create('a', 'b', 'c'); // Compiles
AVar4 := TStringArrayOne.Create('a', 'b', 'c'); // Won't compile
end;
所以TBytes
和TIdBytes
的类型不同,即使它们都被定义为array of Byte
。
关于你的问题2:这是一些第三方代码的常见问题。特别是Indy因进行更改而破坏向后兼容性,因为他们决定在版本之间重新组织或重写内容。 Indy 10是Indy 9,IIRC的一个重大变化,如果您更新到Indy的更高版本(即使没有同时更新Delphi),也几乎需要重写使用它的大多数代码。如果您不想处理这些更改,可能需要考虑使用更稳定的IP通信包。有几种可用的免费开源软件包。
答案 2 :(得分:2)
在Indy 10.5.9中,TIdBytes类型的定义有所不同,具体取决于现有TBytes类型的存在 - 参见单位IdGlobal:
{$IFDEF HAS_TBytes}
TIdBytes = TBytes;
{$ELSE}
TIdBytes = array of Byte;
{$ENDIF}
在Indy 10.6(包含在XE4中)中,声明变为无条件
TIdBytes = array of Byte;
这意味着从Indy 10.6开始,IdGlobal.TIdBytes与SysUtils.TBytes不同。
第二个问题很难回答,更多的是你的优先级问题 - 其他图书馆也不能免受变化影响,例如提高性能或类型安全性。此外,Delphi语言的变化总是会影响现有代码。