Por que recebo o erro “type has no typeinfo” com um tipo enum

Eu declarei o seguinte tipo de enumeração no qual eu quero que o primeiro membro tenha o valor ordinal de 1 (um) em vez do usual 0 (zero):

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

Se eu chamo TypeInfo () , por exemplo, como parte de uma chamada para GetEnumName () , recebo um erro do compilador:

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

ERRO: “E2134: o tipo ‘TMyEnum’ não possui digitação”

Por que é isso?

Eu sei que as classs só tem typeinfo se elas forem compiladas com a opção de compilador $ M ativada ou (derivada de alguma class que foi, como TPersistent ) mas eu não achei que houvesse condições especiais para ter typeinfo para tipos enum.

Enumerações e enumerações descontínuas que não iniciam em zero não têm typeinfo. Para typeinfo a ser implementado, ele precisaria estar em um formato diferente da tkEnumeration existente, devido a problemas de compatibilidade com versões anteriores.

Eu considerei implementar uma tkDiscontiguousEnumeration (ou possivelmente melhor membro nomeado) para o Delphi 2010, mas o benefício pareceu pequeno considerando sua relativa escassez e as dificuldades na enumeração – como você codifica os intervalos eficientemente? Algumas codificações são melhores para alguns cenários e piores para outras.

Não há suporte para informações de tipo para enums onde valores ordinais específicos são atribuídos que resultam em membros de enum com valores ordinais que são diferentes daqueles que normalmente seriam atribuídos pelo compilador.

Se valores específicos forem essenciais ou desejáveis, os membros de enum “não utilizados” deverão ser inseridos para “preencher” o enum conforme necessário. por exemplo (indentação adicional apenas para ênfase):

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

Um subintervalo pode ser usado para “filtrar” o valor inicial não utilizado:

  TValidMyEnum = meFirstValue..meThirdValue; 

Embora você possa querer considerar renomear o tipo de enumeração original para que seu tipo de subintervalo possa ser usado em todo o seu projeto.

Um subintervalo não é suficiente se o enum contiver “gaps”:

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

Neste caso, não existe simplesmente uma maneira de estender a verificação do intervalo em tempo de compilation para excluir os membros não utilizados, mas alguns tipos de conjunto simplificarão o negócio de implementar quaisquer verificações de tempo de execução necessárias:

  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