404
Глава.15 .Перечислимые.типы.и.битовые.флаги
Перечислимые типы подвергаются строгой проверке типов. Например, компиля-
тор
сообщит об ошибке, если в качестве значения я попытаюсь передать методу
тип
Color.Orange
(оранжевый цвет), когда метод ожидает перечислимый тип
Fruit
(фрукт).
В CLR перечислимые типы — это не просто идентификаторы, с которыми имеет
дело компилятор. Перечислимые типы играют важную роль в системе типов, на
них
возлагается решение очень серьезных задач, просто немыслимых для перечислимых
типов в других средах (например, в неуправляемом языке C++).
Каждый перечислимый тип напрямую наследует от типа
System.Enum
, произ-
водного от
System.ValueType
, а тот, в свою очередь, — от
System.Object
. Из
этого
следует, что перечислимые типы относятся к значимым типам (см. главу 5) и могут
выступать как в неупакованной, так и в упакованной формах. Однако в отличие
от других значимых типов, у перечислимого типа не может быть методов, свойств
и событий. Впрочем, как вы увидите в конце данной главы, наличие метода у пере-
числимого типа можно имитировать
при помощи механизма
методов расширения
(extension methods).
При компиляции перечислимого типа компилятор C# превращает каждый
идентификатор в константное поле типа. Например, предыдущее перечисление
Color
компилятор видит примерно так:
internal struct Color : System.Enum {
// Далее перечислены открытые константы,
// определяющие символьные имена и значения
public const Color White = (Color) 0;
public const Color Red = (Color) 1;
public const Color Green = (Color) 2;
public const Color Blue = (Color) 3;
public const Color Orange = (Color) 4;
// Далее находится открытое поле экземпляра со значением переменной Color
// Код с прямой ссылкой на этот экземпляр невозможен
public Int32 value__;
}
Однако компилятор C# не будет обрабатывать такой код, потому что он не
разрешает определять типы, производные от
специального типа
System.Enum
. Это
псевдоопределение всего лишь демонстрирует внутреннюю суть происходящего.
В общем-то, перечислимый тип — это обычная структура, внутри которой описан
набор константных полей и одно экземплярное поле. Константные поля попадают
в метаданные сборки, откуда их можно извлечь с помощью механизма отражения.
Это означает, что в период выполнения можно получить все идентификаторы и их
значения, связанные перечислимым типом, а также преобразовать строковый иден-
тификатор в эквивалентное ему числовое значение. Эти операции предоставлены
базовым
типом
System.Enum
, который предлагает статические и экземплярные
методы, выполняющие специальные операции над экземплярами перечислимых