Delphi使用object编译报E2036错误换record正常,是编译器bug吗?
问题描述
以下代码在Delphi 7和Delphi XE2版本中无法编译,报错信息为E2036 Variable required。但如果将代码中的object替换为record,在支持高级记录特性的Delphi XE2中可以正常编译。原本希望通过IFDEF条件编译,在Delphi 7中使用object、在XE2中使用record来实现跨版本兼容代码,但当前场景下似乎无法实现,请问这是真实存在的编译器bug吗?
type TD = String; TC = object public V: String; function D: TD; end; TB = object public V: String; function C: TC; end; TA = object public V: String; function B: TB; end; function TC.D: TD; begin end; function TB.C: TC; begin end; function TA.B: TB; begin end; procedure Test; var A: TA; s: string; begin s := A.V; // Ok s := A.B.V; // Ok s := A.B.C.V; // "E2036 Variable required", 光标定位在"C"和"."之间 end;
兼容方案
object类型需要至少包含一个虚方法,且其大小不能为0(即至少要有一个数据字段,不需要是V:string这类托管类型)。如下所示的代码可以在Delphi 7中正常编译,定义HAS_ADVANCEDRECORD宏后也可以在Delphi XE2中正常编译:
{.$define HAS_ADVANCEDRECORD} type TE = String; TD = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif} public V: String; function E: TE; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif} end; TC = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif} public V: String; function D: TD; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif} end; TB = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif} public V: String; function C: TC; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif} end; TA = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif} public V: String; function B: TB; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif} end; function TD.E: TE; begin end; function TC.D: TD; begin end; function TB.C: TC; begin end; function TA.B: TB; begin end; procedure Test; var A: TA; s: string; begin s := A.V; //* Ok s := A.B.V; //* Ok s := A.B.C.D.E; //* 已解决:"E2036 Variable required" end;
开发背景说明
该代码原本用于开发一套流式语法的SQL查询构建器,高级记录相比TObject的优势在于不需要进行生命周期管理。使用接口本来是更自然的解决方案,但开发者对接口的使用存在不少问题,后续计划花时间提升对接口的掌握程度。
内容的提问来源于stack exchange,提问作者malom
相关产品推荐
相关产品推荐

