为什么我用枚举类型得到"type has typeinfo"错误

Del*_*ics 19 delphi enums rtti typeinfo

我已经声明了以下枚举类型,其中我希望第一个成员的序数值为1(一)而不是通常的0(零):

  type
    TMyEnum = (
               meFirstValue = 1,
               meSecondValue,
               meThirdValue
              );
Run Code Online (Sandbox Code Playgroud)

如果我调用TypeInfo(),例如作为对GetEnumName()的调用的一部分,我得到一个编译器错误:

  GetEnumName(TypeInfo(TMyEnum), Ord(aValue));
Run Code Online (Sandbox Code Playgroud)

错误:"E2134:类型'TMyEnum'没有typeinfo"

为什么是这样?

我知道,类只有所属类别,如果它们与编译$ M启用编译器选项,或者(在某些类是,如获得TPersistent,但我不认为有具有所属类别的枚举类型的任何特殊情况).

Bar*_*lly 32

不以零开头的不连续枚举和枚举没有typeinfo.对于要实现的typeinfo,由于向后兼容性问题,它需要采用与现有tkEnumeration不同的格式.

我考虑推行tkDiscontiguousEnumeration(或可能更好的命名部件)德尔福2010年,但它的好处似乎是小考虑到其相对稀缺性和在列举的困难 - 你如何有效编码范围?某些编码对某些情况更好,对其他情况则更糟.

  • 这是一些有用且有趣的背景信息.您可能至少考虑更新E2134错误的文档.这提供了一个示例,其中未生成typeinfo,但未提供有关枚举类型的这些注意事项的任何线索.再说一遍,我花了将近15年的坚实德尔菲为我绊倒了,所以你说这不是一个常见的问题.:) (6认同)

Del*_*ics 21

枚举不支持类型信息,其中分配了特定的序数值,导致枚举成员的序数值与编译器通常分配的序数值不同.

如果特定值是必要的或期望的,则必须插入"未使用的"枚举成员以根据需要"填充"枚举.例如(仅用于强调的附加缩进):

  type
    TMyEnum = (
                meNOTUSED1,   {= 0}
               meFirstValue,  {= 1} 
               meSecondValue,
               meThirdValue
              );
Run Code Online (Sandbox Code Playgroud)

然后可以使用子范围"过滤"未使用的初始值:

   TValidMyEnum = meFirstValue..meThirdValue;
Run Code Online (Sandbox Code Playgroud)

虽然您可能希望考虑重命名原始枚举类型,以便您的子范围类型可以在整个项目中使用.

如果枚举包含"间隙",则子范围是不够的:

  type
    TMyEnum = (
                meNOTUSED1,   {= 0}
               meFirstValue,  {= 1} 
               meSecondValue,
               meThirdValue,
                meNOTUSED2,
               meFinalValue   {= 5}
              );
Run Code Online (Sandbox Code Playgroud)

在这种情况下,没有简单的方法来扩展编译时范围检查以排除未使用的成员,但是几种集合类型将简化实现任何必要的运行时检查的业务:

  type
    TMyEnums = set of TMyEnum;

  const
    meNOTUSED      = [meUNUSED1, meUNUSED2]; //  .. etc as required
    meValidValues  = [Low(TMyEnum)..High(TMyEnum)] - meNOTUSED;


  if NOT (aValue in meValidValues) then
     // etc
Run Code Online (Sandbox Code Playgroud)

  • 也许你可以通过使用子范围类型减轻这样做的痛苦:输入TMyEnumWithDummy =(meNOTUSED,meFirstValue,meSecondValue,meThirdValue); TMyEnum = Succ(meNOTUSED)..高(TMyEnumWithDummy); (2认同)
  • 确实是的,尽管如果枚举中有“间隙”,那么简单的子范围是不够的。在我遇到这个问题的情况下,我有差距 - 不幸的是,我对最初的“问题”过于简化了。但我也会用你的建议更新答案。 (2认同)