代码之家  ›  专栏  ›  技术社区  ›  Warren P

Delphi编译器错误E2134是什么意思?

  •  6
  • Warren P  · 技术社区  · 14 年前

    在我正在修复的一些代码中,大量使用了泛型和接口类型,我遇到了错误。

     E2134, Type '<void>' has no type info.

    我认为这是因为我正处于重构过程中,在重构过程中,一些深度嵌套的、所有使用泛型的单元都不同步,但在我可以使用错误消息来修复代码的地方并没有发生错误,因为代码在出现错误的位置没有任何问题。

    这里是上下文,实物模型,因为我不能发布代码,有太多:

     unit GenericThing;
     ...
     interface
     ...
     type
     ...
     IThingListOf<ThingT> = interface( IThingContainer )
        function  getEnumerator: TEnumerator<ThingT>;
        function  getCount: Integer;
        function  getThing( Index: integer ): ThingT;
        function  getFirst: ThingT;
          function  IndexOf( value: ThingT): integer;
        function  addItem( const Thing: ThingT ): ThingT;
          function  removeItem( const Thing: ThingT ): Integer;
        procedure clear;
        procedure Sort; overload;
        procedure Sort(const AComparer: IComparer<ThingT>); overload;
        property  Count: integer read getCount;
        property  First: ThingT read getFirst;
        property  Items[Index: integer]: ThingT read getThing; default;
      end;
    
     // error appears on whatever line number comes after the declaration of  IThingListOf<ThingT>...end; 
      function AnythingYouLikeHere:Integer; // there is nothign wrong with this line, but you get the E2134 here.
    

    问题似乎出在容器本身:

       IThingContainer = interface ...
           ...
           procedure DoSomething(const Param);
       end;
    

    上面的“const param”没有类型信息。在我看来,这是帕斯卡/德尔菲的一个奇怪的(腋窝),在那里你完全违反了维特的强输入的想法。它的弱类型与C中的“void*”指针或Delphi中的“pointer”类型差不多,但很少使用,除了在标准的pre-object pascal rtl函数(如move)等位置。在我看来,在泛型中使用的接口中的非类型化参数应该是允许的,或者是不允许的,但有时是不允许的,其他时候是不允许的。

    这是1978年的Pascal特性与2009年的ObjectPascal特性严重混合的情况。

    2 回复  |  直到 14 年前
        1
  •  15
  •   Barry Kelly    14 年前

    错误消息表示给定类型没有可用的类型信息。

    下面是一个生成消息的最小程序:

    type
      {$M+}
      IThing = interface
        procedure P(const X);
      end;
      {$M-}
    begin
    end.
    

    看来问题是 IThingListOf<> 或其祖先之一,是用 {$M+} 主动的。编译器据此假定 真正地 需要接口的完整类型信息;最初它是由SOAP等支持生成存根等的。接口rtti不支持非类型化参数(逻辑上足够,它们不能由SOAP等进行封送处理),它们显示为void类型,最后出现此错误消息。

    解决方法是要么不使用 {$M+} -虽然假定使用的是RTTI,否则它将无法启用或使用,例如 Pointer 而是显式传递地址。

        2
  •  1
  •   Mason Wheeler    14 年前

    从这一点上说有点难说,尤其是没有可用的容器的定义。如果您将接口定义注释掉,它是否会编译到该点之后?显然,当您试图创建一个实现接口的类时,它会断开,但将其注释掉是不正确的。 问题?

    如果是这样,那么编译器就会扼杀接口定义中的某些内容。试着对部分内容进行评论,找出问题所在。如果没有,那你就得找别的地方了。