2009-09-14 24 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

相關問題