2009-09-14 22 views
16

我声明了以下枚举类型,我希望第一个成员的序数值为1(一)而不是通常的0(零) :为什么我使用枚举类型得到“type has no typeinfo”错误

type 
    TMyEnum = (
       meFirstValue = 1, 
       meSecondValue, 
       meThirdValue 
      ); 

如果我打电话所属类别(),如为GetEnumName一个呼叫的一部分(),我得到一个编译错误:

GetEnumName(TypeInfo(TMyEnum), Ord(aValue)); 

错误: “E2134:类型 'TMyEnum' 没有所属类别”

这是为什么?

我知道类只有所属类别,如果他们启用或$ M编译器选项编译(一些类是派生,如TPersistent),但我不认为有任何特殊条件对于enum类型有typeinfo。

回答

18

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

如果具体的值是必不可少的或可取的,那么必须插入“未使用”的枚举成员以根据需要“填充”枚举。如(仅强调额外的缩进):

type 
    TMyEnum = (
       meNOTUSED1, {= 0} 
       meFirstValue, {= 1} 
       meSecondValue, 
       meThirdValue 
      ); 

的子区域可以被用来“过滤”出未使用的初始值:

TValidMyEnum = meFirstValue..meThirdValue; 

虽然你可能那么不妨考虑重命名原来的枚举键入,以便可以在整个项目中使用您的子范围类型。

的子区域是不够的,如果枚举包含“空白”:

type 
    TMyEnum = (
       meNOTUSED1, {= 0} 
       meFirstValue, {= 1} 
       meSecondValue, 
       meThirdValue, 
       meNOTUSED2, 
       meFinalValue {= 5} 
      ); 

在这种情况下,有没有简单的方法来延长编译时间范围检查,以排除未使用的成员,但一对夫妇设置类型将简化实施任何必要的运行支票业务:

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 
+2

也许可以通过使用一个子界类型减轻这样做的疼痛: 类型 TMyEnumWithDummy =( meNOTUSED, meFirstValue, meSecondValue, meThirdValue ); TMyEnum = Succ(meNOTUSED)..高(TMyEnumWithDummy); – 2009-09-14 09:45:47

+1

是的,虽然如果你在枚举中有“空白”,那么一个简单的子范围是不够的。在遇到这种情况时,我遇到了问题 - 不幸的是,我对最初的“问题”过分简化了。 但是我也会用你的建议更新答案。 – Deltics 2009-09-14 09:53:28

28

不连续枚举和枚举不从零开始没有所属类别。对于要实现的typeinfo,由于向后兼容性问题,它需要采用与现有tkEnumeration不同的格式。

我考虑在Delphi 2010中实现tkDiscontiguousEnumeration(或者可能是更好的命名成员),但考虑到它们相对稀缺和列举困难,好处似乎很小 - 如何有效地对范围进行编码?有些编码对于某些情况更好,对其他编码更糟。

+6

这是一些有用和有趣的背景信息。您可能至少已考虑更新E2134错误的文档。这提供了一个不生成typeinfo的例子,但没有提供关于enum类型的这些注意事项的任何线索。 然后,再次,我花了将近15年的时间,让我绊倒了这一点,所以你说这不是一个普遍的问题。 :) – Deltics 2009-09-14 10:08:23

相关问题