19 Enums
19.1 Generalidades
Um tipo de enum é um tipo de valor distinto (§8.3) que declara um conjunto de constantes nomeadas.
Exemplo: O exemplo
enum Color { Red, Green, Blue }
declara um tipo de enum nomeado
Color
com membrosRed
,Green
eBlue
.Exemplo final
19.2 Declarações Enum
Uma declaração de enum declara um novo tipo de enum. Uma declaração enum começa com a palavra-chave enum
e define o nome, a acessibilidade, o tipo subjacente e os membros do enum.
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 enum tem um tipo integral correspondente chamado o tipo subjacente do tipo de enum. Este tipo subjacente deve poder representar todos os valores do enumerador definidos na enumeração. Se o enum_base estiver presente, ele declara explicitamente o tipo subjacente. O tipo subjacente deve ser um dos tipos integrais (§8.3.6) que não char
. O tipo subjacente pode ser especificado por um integral_type
(§8.3.5) ou por um integral_type_name
. A questão integral_type_name
é resolvida da mesma forma que type_name
(§7.8.1), incluindo tendo em conta quaisquer diretivas de utilização (§14.5).
Nota: O
char
tipo não pode ser usado como um tipo subjacente, seja por palavra-chave ou através de umintegral_type_name
arquivo . Nota final
Uma declaração enum que não declara explicitamente um tipo subjacente tem um tipo subjacente de int
.
Exemplo: O exemplo
enum Color : long { Red, Green, Blue }
declara um enum com um tipo subjacente de
long
.Exemplo final
Nota: Um desenvolvedor pode optar por usar um tipo subjacente de
long
, como no exemplo, para habilitar o uso de valores que estão no intervalo delong
, mas não no intervalo deint
, ou para preservar essa opção para o futuro. Nota final
Nota: C# permite uma vírgula à direita em um enum_body, assim como permite uma em um array_initializer (§17.7). Nota final
Uma declaração enum não pode incluir uma lista de parâmetros de tipo, mas qualquer enum aninhado dentro de uma declaração de classe genérica ou uma declaração struct genérica é uma declaração enum genérica, uma vez que os argumentos de tipo para o tipo que contém devem ser fornecidos para criar um tipo construído (§8.4).
19.3 Modificadores de enum
Um enum_declaration pode, opcionalmente, incluir uma sequência de modificadores de enum:
enum_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
;
É um erro em tempo de compilação para o mesmo modificador aparecer várias vezes em uma declaração enum.
Os modificadores de uma declaração de enum têm o mesmo significado que os de uma declaração de classe (§15.2.2). No entanto, os abstract
modificadores , e sealed
, e static
não são permitidos em uma declaração de enum. Enums não podem ser abstratos e não permitem derivação.
19.4 Membros Enum
O corpo de uma declaração de tipo enum define zero ou mais membros enum, que são as constantes nomeadas do tipo enum. Não há dois membros enum que possam ter o mesmo nome.
enum_member_declarations
: enum_member_declaration (',' enum_member_declaration)*
;
enum_member_declaration
: attributes? identifier ('=' constant_expression)?
;
Cada membro do enum tem um valor constante associado. O tipo deste valor é o tipo subjacente para o enum que contém. O valor constante para cada membro do enum deve situar-se no intervalo do tipo subjacente para o eno.
Exemplo: O exemplo
enum Color: uint { Red = -1, Green = -2, Blue = -3 }
resulta em um erro em tempo de compilação porque os valores
-1
constantes ,-2
, e-3
não estão no intervalo do tipouint
integral subjacente.Exemplo final
Vários membros do enum podem compartilhar o mesmo valor associado.
Exemplo: O exemplo
enum Color { Red, Green, Blue, Max = Blue }
mostra um enum no qual dois membros do enum —
Blue
eMax
—têm o mesmo valor associado.Exemplo final
O valor associado de um membro enum é atribuído implícita ou explicitamente. Se a declaração do membro enum tiver um inicializador constant_expression , o valor dessa expressão constante, implicitamente convertido para o tipo subjacente do enum, é o valor associado do membro enum. Se a declaração do membro enum não tiver inicializador, seu valor associado será definido implicitamente, da seguinte forma:
- Se o membro enum for o primeiro membro enum declarado no tipo enum, seu valor associado será zero.
- Caso contrário, o valor associado do membro enum é obtido aumentando o valor associado do membro enum textualmente anterior em um. Este valor acrescido deve situar-se dentro do intervalo de valores que pode ser representado pelo tipo subjacente, caso contrário ocorre um erro em tempo de compilação.
Exemplo: O exemplo
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 os nomes dos membros do ENUM e seus valores associados. A saída é:
Red = 0 Green = 10 Blue = 11
pelos seguintes motivos:
- ao membro
Red
enum é automaticamente atribuído o valor zero (uma vez que não tem inicializador e é o primeiro membro enum);- ao membro
Green
enum é explicitamente dado o valor10
;- e ao membro
Blue
enum é automaticamente atribuído o valor um maior do que o membro que textualmente o precede.Exemplo final
O valor associado de um membro enum não pode, direta ou indiretamente, utilizar o valor do seu próprio membro enum associado. Além desta restrição de circularidade, os inicializadores de membros de enum podem referir-se livremente a outros inicializadores de membros de enum, independentemente de sua posição textual. Dentro de um inicializador de membro de enum, os valores de outros membros de enum são sempre tratados como tendo o tipo de seu tipo subjacente, de modo que os moldes não são necessários quando se referem a outros membros de enum.
Exemplo: O exemplo
enum Circular { A = B, B }
resulta em um erro em tempo de compilação porque as declarações de
A
eB
são circulares.A
depende deB
explicitamente, eB
depende deA
implicitamente.Exemplo final
Os membros do Enum são nomeados e definidos de forma exatamente análoga aos campos dentro das classes. O escopo de um membro enum é o corpo de seu tipo de enum. Neste âmbito, os membros do enum podem ser referidos pelo seu nome simples. De todos os outros códigos, o nome de um membro do enum deve ser qualificado com o nome do seu tipo de enum. Os membros do Enum não têm nenhuma acessibilidade declarada — um membro do Enum é acessível se o seu tipo de enum que contém estiver acessível.
19.5 O tipo System.Enum
O tipo System.Enum
é a classe base abstrata de todos os tipos de enum (isto é distinto e diferente do tipo subjacente do tipo de enum), e os membros herdados de estão disponíveis em qualquer tipo de System.Enum
enum. Existe uma conversão de boxe (§10.2.9) de qualquer tipo de enum para System.Enum
, e uma conversão de unboxing (§10.3.7) de para qualquer tipo de System.Enum
enum.
Note-se que System.Enum
não é em si um enum_type. Pelo contrário, é um class_type do qual derivam todos os enum_types. O tipo System.Enum
herda do tipo System.ValueType
(§8.3.2), que, por sua vez, herda do tipo object
. Em tempo de execução, um valor do tipo System.Enum
pode ser null
ou uma referência a um valor in a box de qualquer tipo de enum.
19.6 Valores e operações Enum
Cada tipo de enum define um tipo distinto; Uma conversão de enumeração explícita (§10.3.3) é necessária para converter entre um tipo de enum e um tipo integral, ou entre dois tipos de enum. O conjunto de valores do tipo enum é o mesmo que o conjunto de valores do tipo subjacente e não se restringe aos valores das constantes nomeadas. Qualquer valor do tipo subjacente de um enum pode ser convertido para o tipo enum, e é um valor válido distinto desse tipo de enum.
Os membros do Enum têm o tipo do seu tipo de enum (exceto dentro de outros inicializadores de membros do enum: ver §19.4). O valor de um membro enum declarado no tipo E
enum com valor v
associado é (E)v
.
Os seguintes operadores podem ser usados em valores de tipos de enum:
==
, , , , , (>=
§12.12.6)<=
>
<
!=
- binário
+
(§12.10.5) - binário
-
(§12.10.6) ^
,&
,|
(§12.13.3)~
(ponto 12.9.5)++
,--
(§12.8.15 e §12.9.6)sizeof
(ponto 23.6.9)
Cada tipo de enum deriva automaticamente da classe System.Enum
(que, por sua vez, deriva de System.ValueType
e object
). Assim, métodos herdados e propriedades desta classe podem ser usados em valores de um tipo de enum.
ECMA C# draft specification