19 Enumeraciones
19.1 General
Un tipo de enumeración es un tipo de valor distinto (§8.3) que declara un conjunto de constantes con nombre.
Ejemplo: El ejemplo
enum Color { Red, Green, Blue }
declara un tipo de enumeración denominado
Color
con miembrosRed
,Green
yBlue
.ejemplo final
19.2 Declaraciones de enumeración
Una declaración de enumeración declara un nuevo tipo de enumeración. Una declaración de enumeración comienza con la palabra clave enum
y define el nombre, la accesibilidad, el tipo subyacente y los miembros de la enumeración.
enum_declaration
: attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'?
;
enum_base
: ':' integral_type
| ':' integral_type_name
;
integral_type_name
: type_name // Shall resolve to an integral type other than char
;
enum_body
: '{' enum_member_declarations? '}'
| '{' enum_member_declarations ',' '}'
;
Cada tipo de enumeración tiene un tipo entero correspondiente denominado tipo subyacente del tipo de enumeración. Este tipo subyacente podrá representar todos los valores del enumerador definidos en la enumeración. Si el enum_base está presente, declara explícitamente el tipo subyacente. El tipo subyacente debe ser uno de los tipos enteros (§8.3.6) distintos de char
. El tipo subyacente puede especificarse mediante (integral_type
§8.3.5) o un integral_type_name
. Se integral_type_name
resuelve de la misma manera que type_name
(§7.8.1), incluida la posibilidad de tener en cuenta las directivas using (§14.5).
Nota: El
char
tipo no se puede usar como un tipo subyacente, ya sea por palabra clave o a través de .integral_type_name
nota final
Una declaración de enumeración que no declara explícitamente un tipo subyacente tiene un tipo subyacente de int
.
Ejemplo: El ejemplo
enum Color : long { Red, Green, Blue }
declara una enumeración con un tipo subyacente de
long
.ejemplo final
Nota: Un desarrollador puede optar por usar un tipo subyacente de
long
, como en el ejemplo, para habilitar el uso de valores que se encuentran en el intervalo delong
, pero no en el intervalo deint
, o para conservar esta opción para el futuro. nota final
Nota: C# permite una coma final en un enum_body, al igual que permite una en un array_initializer (§17.7). nota final
Una declaración de enumeración no puede incluir una lista de parámetros de tipo, pero cualquier enumeración anidada dentro de una declaración de clase genérica o una declaración de estructura genérica es una declaración de enumeración genérica, ya que se proporcionarán argumentos de tipo para el tipo contenedor para crear un tipo construido (§8.4).
Modificadores de enumeración 19.3
Un enum_declaration puede incluir opcionalmente una secuencia de modificadores de enumeración:
enum_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
;
Es un error en tiempo de compilación para que el mismo modificador aparezca varias veces en una declaración de enumeración.
Los modificadores de una declaración de enumeración tienen el mismo significado que los de una declaración de clase (§15.2.2). Sin embargo, los abstract
modificadores , y sealed
y static
no se permiten en una declaración de enumeración. Las enumeraciones no pueden ser abstractas y no permiten la derivación.
19.4 Miembros de enumeración
El cuerpo de una declaración de tipo de enumeración define cero o más miembros de enumeración, que son las constantes con nombre del tipo de enumeración. No hay dos miembros de enumeración que tengan el mismo nombre.
enum_member_declarations
: enum_member_declaration (',' enum_member_declaration)*
;
enum_member_declaration
: attributes? identifier ('=' constant_expression)?
;
Cada miembro de enumeración tiene un valor constante asociado. El tipo de este valor es el tipo subyacente para la enumeración contenedora. El valor constante de cada miembro de enumeración estará en el intervalo del tipo subyacente de la enumeración.
Ejemplo: El ejemplo
enum Color: uint { Red = -1, Green = -2, Blue = -3 }
produce un error en tiempo de compilación porque los valores constantes
-1
,-2
y-3
no están en el intervalo del tipouint
entero subyacente .ejemplo final
Varios miembros de enumeración pueden compartir el mismo valor asociado.
Ejemplo: El ejemplo
enum Color { Red, Green, Blue, Max = Blue }
muestra una enumeración en la que dos miembros de enumeración (
Blue
yMax
) tienen el mismo valor asociado.ejemplo final
El valor asociado de un miembro de enumeración se asigna implícita o explícitamente. Si la declaración del miembro de enumeración tiene un inicializador constant_expression , el valor de esa expresión constante, convertido implícitamente al tipo subyacente de la enumeración, es el valor asociado del miembro de enumeración. Si la declaración del miembro de enumeración no tiene inicializador, su valor asociado se establece implícitamente, como se indica a continuación:
- Si el miembro de enumeración es el primer miembro de enumeración declarado en el tipo de enumeración, su valor asociado es cero.
- De lo contrario, el valor asociado del miembro de enumeración se obtiene aumentando el valor asociado del miembro de enumeración de texto anterior por uno. Este valor aumentado estará dentro del intervalo de valores que se pueden representar mediante el tipo subyacente; de lo contrario, se produce un error en tiempo de compilación.
Ejemplo: El ejemplo
enum Color { Red, Green = 10, Blue } class Test { static void Main() { Console.WriteLine(StringFromColor(Color.Red)); Console.WriteLine(StringFromColor(Color.Green)); Console.WriteLine(StringFromColor(Color.Blue)); } static string StringFromColor(Color c) { switch (c) { case Color.Red: return $"Red = {(int) c}"; case Color.Green: return $"Green = {(int) c}"; case Color.Blue: return $"Blue = {(int) c}"; default: return "Invalid color"; } } }
imprime los nombres de miembro de enumeración y sus valores asociados. La salida es la siguiente:
Red = 0 Green = 10 Blue = 11
por los siguientes motivos:
- Al miembro
Red
de enumeración se le asigna automáticamente el valor cero (ya que no tiene inicializador y es el primer miembro de enumeración);- el miembro
Green
de enumeración recibe explícitamente el valor10
;- y al miembro
Blue
de enumeración se le asigna automáticamente el valor uno mayor que el miembro que lo precede textualmente.ejemplo final
El valor asociado de un miembro de enumeración no utilizará, directa o indirectamente, el valor de su propio miembro de enumeración asociado. Aparte de esta restricción de circularidad, los inicializadores de miembros de enumeración pueden hacer referencia libremente a otros inicializadores de miembro de enumeración, independientemente de su posición textual. Dentro de un inicializador de miembro de enumeración, los valores de otros miembros de enumeración siempre se tratan como tener el tipo de su tipo subyacente, por lo que las conversiones no son necesarias al hacer referencia a otros miembros de enumeración.
Ejemplo: El ejemplo
enum Circular { A = B, B }
produce un error en tiempo de compilación porque las declaraciones de
A
yB
son circulares.A
depende explícitamenteB
de yB
depende implícitamenteA
.ejemplo final
Los miembros de enumeración se denominan y tienen como ámbito exactamente análogos a los campos dentro de las clases. El ámbito de un miembro de enumeración es el cuerpo de su tipo de enumeración contenedor. Dentro de ese ámbito, se puede hacer referencia a los miembros de enumeración por su nombre simple. A partir del resto del código, el nombre de un miembro de enumeración se calificará con el nombre de su tipo de enumeración. Los miembros de enumeración no tienen ninguna accesibilidad declarada: se puede acceder a un miembro de enumeración si se puede acceder a su tipo de enumeración contenedora.
19.5 El tipo System.Enum
El tipo System.Enum
es la clase base abstracta de todos los tipos de enumeración (es distinto y diferente del tipo subyacente del tipo de enumeración) y los miembros heredados de System.Enum
están disponibles en cualquier tipo de enumeración. Existe una conversión boxing (§10.2.9) desde cualquier tipo de enumeración a System.Enum
y existe una conversión de unboxing (§10.3.7) de System.Enum
a cualquier tipo de enumeración.
Tenga en cuenta que System.Enum
no es un enum_type. En su lugar, es un class_type del que se derivan todos los enum_type. El tipo System.Enum
hereda del tipo System.ValueType
(§8.3.2), que, a su vez, hereda del tipo object
. En tiempo de ejecución, un valor de tipo System.Enum
puede ser null
o una referencia a un valor boxed de cualquier tipo de enumeración.
19.6 Valores y operaciones de enumeración
Cada tipo de enumeración define un tipo distinto; Se requiere una conversión de enumeración explícita (§10.3.3) para convertir entre un tipo de enumeración y un tipo entero, o entre dos tipos de enumeración. El conjunto de valores del tipo de enumeración es el mismo que el conjunto de valores del tipo subyacente y no está restringido a los valores de las constantes con nombre. Cualquier valor del tipo subyacente de una enumeración se puede convertir al tipo de enumeración y es un valor válido distinto de ese tipo de enumeración.
Los miembros de enumeración tienen el tipo de su tipo de enumeración contenedor (excepto dentro de otros inicializadores de miembro de enumeración: consulte §19.4). El valor de un miembro de enumeración declarado en el tipo E
de enumeración con el valor v
asociado es (E)v
.
Los operadores siguientes se pueden usar en valores de tipos de enumeración:
==
,!=
,<
,>
, ,>=
<=
(§12.12.6)- binary
+
(§12.10.5) - binary
-
(§12.10.6) ^
, ,&
|
(§12.13.3)~
(§12.9.5)++
,--
(§12.8.15 y §12.9.6)sizeof
(§23.6.9)
Cada tipo de enumeración deriva automáticamente de la clase System.Enum
(que, a su vez, deriva de System.ValueType
y object
). Por lo tanto, los métodos heredados y las propiedades de esta clase se pueden usar en valores de un tipo de enumeración.
ECMA C# draft specification