На заметку! По соглашению имена типов перечислений обычно снабжаются суффиксом
Enum
.
Поступать так необязательно, но подобный подход улучшает читабельность кода.
В перечислении
EmpTypeEnum
определены четыре именованные константы, которые соответствуют дискретным числовым значениям. По умолчанию первому элементу присваивается значение
0
, а остальным элементам значения устанавливаются по схеме n+1. При желании исходное значение можно изменять подходящим образом. Например, если имеет смысл нумеровать члены
EmpTypeEnum
со значения 102 до 105, тогда можно поступить следующим образом:
// Начать нумерацию со значения 102.
enum EmpTypeEnum
{
Manager = 102,
Grunt, // = 103
Contractor, // = 104
VicePresident // = 105
}
Нумерация в перечислениях не обязана быть последовательной и содержать только уникальные значения. Если (по той или иной причине) перечисление
EmpTypeEnum
необходимо сконфигурировать так, как показано ниже, то компиляция пройдет гладко и без ошибок:
// Значения элементов в перечислении не обязательно должны
// быть последовательными!
enum EmpType
{
Manager = 10,
Grunt = 1,
Contractor = 100,
VicePresident = 9
}
Управление хранилищем, лежащим в основе перечисления
По умолчанию для хранения значений перечисления используется тип
System.Int32
(
int
в языке С#); тем не менее, при желании его легко заменить. Перечисления в C# можно определять в похожей манере для любых основных системных типов (
byte
,
short
,
int
или
long
). Например, чтобы значения перечисления
EmpTypeEnum
хранились с применением типа
byte
, а не
int
, можно записать так:
// На этот раз для элементов EmpTypeEnum используется тип byte.
enum EmpTypeEnum : byte
{
Manager = 10,
Grunt = 1,
Contractor = 100,
VicePresident = 9
}
Изменение типа, лежащего в основе перечисления, может быть полезным при построении приложения .NET Core, которое планируется развертывать на устройствах с небольшим объемом памяти, а потому необходимо экономить память везде, где только возможно. Конечно, если в качестве типа хранилища для перечисления указан
byte
, то каждое значение должно входить в диапазон его допустимых значений. Например, следующая версия
EmpTypeEnum
приведет к ошибке на этапе компиляции, т.к. значение 999 не умещается в диапазон допустимых значений типа
byte
:
// Ошибка на этапе компиляции! Значение 999 слишком велико для типа byte!
enum EmpTypeEnum : byte
{
Manager = 10,
Grunt = 1,
Contractor = 100,
VicePresident = 999
}
Объявление переменных
типа перечисления
После установки диапазона и типа хранилища перечисление можно использовать вместо так называемых "магических чисел". Поскольку перечисления — всего лишь определяемые пользователем типы данных, их можно применять как возвращаемые значения функций, параметры методов, локальные переменные и т.д. Предположим, что есть метод по имени
AskForBonus
, который принимает в качестве единственного параметра переменную
EmpTypeEnum
. На основе значения входного параметра в окно консоли будет выводиться подходящий ответ на запрос о надбавке к зарплате.
Console.WriteLine("**** Fun with Enums *****");
// Создать переменную типа EmpTypeEnum.
EmpTypeEnum emp = EmpTypeEnum.Contractor;
AskForBonus(emp);
Console.ReadLine;
// Перечисления как параметры.
static void AskForBonus(EmpTypeEnum e)
{
switch (e)
{
case EmpType.Manager:
Console.WriteLine("How about stock options instead?");
// He желаете ли взамен фондовые опционы?
break;
case EmpType.Grunt:
Console.WriteLine("You have got to be kidding...");
// Вы должно быть шутите...
break;
case EmpType.Contractor:
Console.WriteLine("You already get enough cash...");
// Вы уже получаете вполне достаточно...
break;
case EmpType.VicePresident:
Console.WriteLine("VERY GOOD, Sir!");
// Очень хорошо, сэр!
break;
}
}
Обратите внимание, что когда переменной
enum
присваивается значение, вы должны указывать перед этим значением (
Grunt
) имя самого перечисления (
EmpTypeEnum
). Из-за того, что перечисления представляют собой фиксированные наборы пар "имя-значение", установка переменной
enum
в значение, которое не определено прямо в перечислимом типе, не допускается:
static void ThisMethodWillNotCompile
{
// Ошибка! SalesManager отсутствует в перечислении EmpTypeEnum!
EmpTypeEnum emp = EmpType.SalesManager;
// Ошибка! He указано имя EmpTypeEnum перед значением Grunt!
emp = Grunt;
}
Использование типа System.Enum
С перечислениями .NET Core связан один интересный аспект — они получают свою функциональность от класса
System.Enum
. В классе
System.Enum
определено множество методов, которые позволяют исследовать и трансформировать заданное перечисление. Одним из них является метод
Enum.GetUnderlyingType
, который возвращает тип данных, используемый для хранения значений перечислимого типа (
System.Byte
в текущем объявлении
EmpTypeEnum
):
Console.WriteLine("**** Fun with Enums *****");
...
// Вывести тип хранилища для значений перечисления.
Console.WriteLine("EmpTypeEnum uses a {0} for storage",
Enum.GetUnderlyingType(emp.GetType));
Console.ReadLine;
Метод
Enum.GetUnderlyingType
требует передачи
System.Type
в качестве первого параметра. В главе 15 будет показано, что класс
Туре
представляет описание метаданных для конкретной сущности .NET Core.