Перечислимые типы
Перечислимым
(enumerated type) называют тип, в котором описан набор пар, со-
стоящих из символьных имен и значений. Далее приведен тип
Color
, определяющий
совокупность идентификаторов, каждый из которых обозначает определенный цвет:
internal enum Color {
White, // Присваивается значение 0
Red, // Присваивается значение 1
Green, // Присваивается значение 2
Blue, // Присваивается значение 3
Orange // Присваивается значение 4
}
Конечно, в программе можно вместо
White
написать 0, вместо
Green
— 1 и т. д.
Однако перечислимый тип все-таки лучше жестко заданных в исходном коде чис-
ловых значений по крайней мере по двум причинам.
Программу, где используются перечислимые типы, проще написать и понять,
а у разработчиков возникает меньше проблем с ее сопровождением. Символь-
ное имя перечислимого типа проходит через весь код, и занимаясь то одной, то
другой частью программы, программист не обязан помнить значение каждого
«зашитого» в коде значения (что
White
равен 0, а 0 означает
White
). Если же
числовое значение символа почему-либо изменилось, то нужно только пере-
компилировать исходный код, не изменяя в нем ни буквы. Кроме того, работая
с инструментами документирования и другими утилитами, такими как отладчик,
программист видит осмысленные символьные имена, а не цифры.
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
, который предлагает статические и экземплярные
методы, выполняющие специальные операции над экземплярами перечислимых
Do'stlaringiz bilan baham: |