Perché ottengo l’errore “type non ha typeinfo” con un tipo enum

Ho dichiarato il seguente tipo di enum in cui voglio che il primo membro abbia il valore ordinale di 1 (uno) piuttosto che il solito 0 (zero):

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

Se chiamo TypeInfo () , ad esempio come parte di una chiamata a GetEnumName () , ottengo un errore del compilatore:

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

ERRORE: “E2134: digitare ‘TMyEnum’ non ha typeinfo

Perchè è questo?

So che le classi hanno solo typeinfo se sono compilate con l’opzione $ M del compilatore abilitata o (derivano da una class che era, come TPersistent ) ma non pensavo ci fossero condizioni speciali per avere typeinfo per i tipi di enum.

Enumerazioni ed enumerazioni discontinue che non partono da zero non hanno typeinfo. Affinché typeinfo possa essere implementato, dovrebbe essere in un formato diverso dall’esistente tkEnumeration, a causa di problemi di compatibilità con le versioni precedenti.

Ho preso in considerazione l’implementazione di un tkDiscontiguousEnumeration (o forse un membro con un nome migliore) per Delphi 2010, ma il vantaggio sembrava piccolo considerando la loro relativa scarsità e le difficoltà di enumerazione – come si codificano gli intervalli in modo efficiente? Alcune codifiche sono migliori per alcuni scenari, peggio per gli altri.

Le informazioni sul tipo non sono supportate per le enumerazioni in cui sono assegnati specifici valori ordinali che danno luogo a membri enum con valori ordinali diversi da quelli che verrebbero normalmente assegnati dal compilatore.

Se i valori specifici sono essenziali o desiderabili, i membri dell’enum “inutilizzati” dovranno essere inseriti per “riempire” l’enum come richiesto. ad esempio (indentazione aggiuntiva per enfasi solo):

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

Un subrange può quindi essere utilizzato per “filtrare” il valore iniziale non utilizzato:

  TValidMyEnum = meFirstValue..meThirdValue; 

Sebbene si possa decidere di rinominare il tipo di enum originale in modo che il tipo di subrange possa essere utilizzato nel progetto.

Un subrange non è sufficiente se l’enum contiene “gap”:

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

In questo caso non esiste un modo semplice per estendere il controllo dell’intervallo in fase di compilazione per escludere i membri non utilizzati, ma un paio di tipi di insieme semplificheranno l’attività di implementazione di eventuali controlli runtime necessari:

  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