Partilhar via


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 membros Red, Greene Blue.

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 enume 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 um integral_type_namearquivo . 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 de long , mas não no intervalo de int, 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 abstractmodificadores , 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 -1constantes , -2, e -3 não estão no intervalo do tipo uintintegral 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 e Max—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 valor 10;
  • 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 e B são circulares. A depende de B explicitamente, e B depende de A 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:

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.