Почему я получаю & # 8220; тип не имеет typeinfo & # 8221; ошибка с типом enum

StackOverflow https://stackoverflow.com/questions/1420562

  •  07-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

Почему это?

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

Это было полезно?

Решение 2

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

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

  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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top