Почему я получаю сообщение об ошибке «type not type type» с типом enum - PullRequest
19 голосов
/ 14 сентября 2009

Я объявил следующий тип перечисления, в котором я хочу, чтобы первый член имел порядковый номер 1 (один), а не обычный 0 (ноль):

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

Если я позвоню TypeInfo () , например как часть вызова GetEnumName () , я получаю ошибку компилятора:

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

ОШИБКА: "E2134: Тип 'TMyEnum' не имеет информации о типе"

Почему это?

Я знаю, что классы имеют typeinfo только в том случае, если они скомпилированы с включенной опцией компилятора $ M или (производной от некоторого класса, который был, например, TPersistent ), но я этого не сделал Не думаю, что были какие-то особые условия для наличия typeinfo для перечислимых типов.

Ответы [ 2 ]

30 голосов
/ 14 сентября 2009

Непрерывные перечисления и перечисления, которые не начинаются с нуля, не имеют typeinfo. Для реализации typeinfo он должен быть в другом формате, чем существующий tkEnumeration, из-за проблем обратной совместимости.

Я подумал о реализации tkDiscontiguousEnumeration (или, возможно, члена с более точным именем) для Delphi 2010, но выгода выглядела небольшой, учитывая их относительную нехватку и трудности с перечислением - как эффективно кодировать диапазоны? Некоторые кодировки лучше для одних сценариев, хуже для других.

21 голосов
/ 14 сентября 2009

Информация о типе не поддерживается для перечислений, где присваиваются конкретные порядковые значения, в результате чего члены перечисления имеют порядковые значения, отличающиеся от тех, которые обычно назначаются компилятором.

Если конкретные значения необходимы или желательны, «неиспользуемые» элементы перечисления должны быть вставлены для «дополнения» перечисления по мере необходимости. например (дополнительный отступ только для выделения):

  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
...