Почему я получаю & # 8220; тип не имеет typeinfo & # 8221; ошибка с типом enum
Вопрос
Я объявил следующий тип перечисления, в котором я хочу, чтобы первый член имел порядковый номер 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, но выгода выглядела небольшой, учитывая их относительную нехватку и трудности с перечислением - как эффективно кодировать диапазоны? Некоторые кодировки лучше для одних сценариев, хуже для других.