Enums em C#: Simplificando a Gestão de Constantes
Tags: csharp, enumeration, programming, beginners
Published: 2024-06-27 21:59:23

**Enumeração** ou **Enum** é um recurso muito legal em Desenvolvimento de Software. Ele nos permite representar um conjunto fixo de valores relacionados, facilitando leitura e manutenção de código.

Em outras palavras mais técnicas:

> Em programação, uma enumeração é um tipo de dado abstrato, cujos valores são atribuídos a exatamente um elemento de um conjunto finito de identificadores escolhidos pelo programador. [Wikipedia](https://pt.wikipedia.org/wiki/Enumera%C3%A7%C3%A3o_(tipo_de_dado)#:~:text=Em%20programa%C3%A7%C3%A3o%2C%20uma%20enumera%C3%A7%C3%A3o%20%C3%A9,possuem%20uma%20ordem%20num%C3%A9rica%20definida.)

A maioria das linguagens tipadas, como Java, TypeScript, Swift, Kotlin, Rust, C++, etc. possuem Enum. Neste post, estarei explicando como a mesma funciona em C#.

## Enum em `C#`
Em c#, um enum é definido usando a palavra-chave `enum`, seguido pelo nome do enum e uma "lista" de seus membros entre chaves:

```csharp
public enum Status
{
    Active,
    Inactive,
    Pending
}
```

Acima estou utilizando o exemplo de estados de pedidos, como: Ativo, Inativo e Pendente. Mas pode ser outros casos, como dias da semana, tipos de documento(CPF, CNPJ, RG), etc.

Um exemplo de uso:

```csharp
public class Order
{
    public int Id { get; set; }
    public Status OrderStatus { get; set; }
}

var order = new Order { Id = 1, OrderStatus = Status.Active };

if (order.OrderStatus == Status.Active)
{
    Console.WriteLine("The order is active.");
}
```

Há a possibilidade de você atribuir valores inteiros aos enums, com isso você pode controlar a representação dos estados ou opções:

```c#
public enum Priority
{
    Low = 1,
    Medium = 2,
    High = 3
}
```

`Enums` em C# não podem ser iniciados com valores nulos, pois `Enum` é um **[tipo de valor](https://learn.microsoft.com/pt-br/dotnet/csharp/language-reference/builtin-types/value-types)**, o que significa que eles sempre têm um valor atribuído e não podem ser null.

### Compilador

O **compilador** associa cada membro do enum a um valor inteiro sequencial. Por padrão, o primeiro começa com o valor `0`, o segundo como `1`, e assim por diante.
Durante a compilação, o compilador substitui os nomes das propriedades de um enum pelo valor inteiro correspondente. Isso significa que, internamente, o código que usa um enum como `Status.Active` é substituído por um valor inteiro (por exemplo, 0 se for o primeiro membro não atribuído).

Estruturas de controle como switches em C# e Java são otimizadas para enums. O compilador muitas vezes gera instruções de desvio direto (jump tables) para lidar eficientemente com enums, o que significa que o tempo de acesso é constante e independente do número de membros do enum.

### Memória

Enums são tipos de valor, o que significa que eles são armazenados como valores diretos em memória(o que facilita a eficiência) geralmente como inteiros. Em sistemas que otimizam o espaço de armazenamento, enums podem ser armazenados como o menor tipo inteiro que pode acomodar todos os valores do enum.

Como enums são representados internamente como valores inteiros (ou outro tipo de valor dependendo da linguagem), o acesso a qualquer valor de enum é direto `O(1)`. Não há necessidade de cálculos adicionais ou pesquisas, pois o valor do enum é determinado em tempo de compilação e acessado diretamente em tempo de execução.

### Enum para String ou vice Versa

É possível converter um Enum para string ou string para um Enum, vamos ver alguns casos de **Enum para string**:

#### ToString()

```c#
Status statusPending = Status.Pending;
string statusPendingString = statusPending.ToString(); // saida -> "Pending"
```

Esse caso acima é um caso simples.

#### Enum.GetName()

Você pode usar Enum.GetName() para obter o nome de um membro específico de um enum. Este método retorna o nome do identificador que corresponde ao valor do enum especificado.

```c#
Status statusActive = Status.Active;
string statusActiveString = Enum.GetName(statusActive); // saída -> "Active"
```

#### nameof()

Veremos outro utilizando o `nameof()`

```c#
string statusActiveString = nameof(Status.Active); // saida -> "Active"
```

**MUITO CUIDADO AO UTILIZAR `nameof()` ao converter enum para string**

Se você reparar bem, os dois exemplos são diferentes, no primeiro exemplo, eu declaro a variável como sendo um `enum` acima e abaixo converto para `string`. No segundo exemplo eu não fiz isso, por que? Vejamos o exemplo abaixo

```c#
Status statusPending = Status.Pending;
string statusPendingString = nameof(statusPending); 
```

A saída desse programa acima não é "Pending", mas sim o nome da variável "statusPending", curioso, né? Isso ocorre porque o `nameof() ` é avaliado **somente em tempo de compilação** e retorna o nome do identificador que é passado pra ele, não o valor da expressão. Então quando passamos `nameof(Status.Pending)`, ele funciona nesse contexto porque o argumento passado é a referência ao membro do Enum Pending.

## Convertendo string para Enum

#### Enum.Parse()

```c#
string statusActiveString = "Active";
Status statusActive = Enum.Parse<Status>(statusActiveString);
```

#### Enum.TryParse()

```c#
string statusPendingString = "Pending";
bool tryParse = Enum.TryParse(statusPendingString, out Status status);
```

Chegamos ao final de mais um post. Estarei deixando alguns links de referência:

[Tipos de enumeração (referência de C#)](https://learn.microsoft.com/pt-br/dotnet/csharp/language-reference/builtin-types/enum)
[Enums C#](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/enums)

Um abraço e bons estudos! Até mais.