A arte das coleções em .NET - List
Published: 2023-04-13 13:00:00

Com certeza você já precisou lidar com dados e optou por usar List, seja por toda a praticidade que esta classe proporciona ou por ser uma das mais difundidas. Uma das perguntas que eu mais gosto de me fazer quando estou programando é: por que vou usar isto aqui? Essa é uma das perguntas que vamos responder agora no segundo artigo da série sobre coleções.

## Definindo a List
Como vimos no [artigo anterior](https://dev.to/unhacked/a-arte-das-colecoes-em-net-intro-j9a), a recomendação é usar coleções genéricas, então encontramos a classe `List<T>` no _namespace_ System.Collections.Generic. A `List<T>` representa uma lista fortemente tipada de objetos que podem ser acessados por índice e possui métodos para pesquisar, classificar e manipular as listas. Por baixo dos panos, a `List<T>` é um array unidimensional que começa em índice zero.

## Utilizando a `List<T>`
Para inicializar uma lista do tipo Aluno, escrevemos assim:
```
List<Aluno> alunos = new List<Aluno>();
```
Ao utilizarmos o construtor sem parâmetros, iremos criar uma lista com a capacidade padrão, que é 4. Após a inicialização, podemos adicionar itens à lista usando o método Add() passando o objeto aluno como parâmetro, assim:
```
alunos.Add(new Aluno { Id = 1, Nome = "Thaise" });
```
Agora aqui é a dica de ouro para otimizar seu código usando `List<T>` com uma grande quantidade de itens! Se não definirmos a capacidade, o .NET vai criar uma com capacidade para até 4 itens, que é o padrão. Toda vez que um item é adicionado, é verificado se a capacidade da lista comporta mais um item. Caso a capacidade seja menor que a quantidade de itens mais 1, que estamos tentando adicionar, será criada uma nova lista com a capacidade duplicada e os itens da lista atual serão copiados para a nova. 

Por exemplo: no nosso código acima, criamos uma lista de alunos usando o construtor sem parâmetros e adicionamos um aluno nela. Neste momento, temos uma lista de alunos com capacidade para até 4 itens e um item adicionado. Agora vamos inserir mais 3 itens:
```
alunos.Add(new Aluno { Id = 2, Nome = "Ana" });
alunos.Add(new Aluno { Id = 3, Nome = "Cristiano" });
alunos.Add(new Aluno { Id = 4, Nome = "Maggie" });
```
Neste momento ainda temos uma lista com capacidade para até 4 itens e agora com 4 itens. Isso significa que estamos utilizando a capacidade máxima. Quando adicionarmos mais um item, a verificação para saber se a lista comporta mais um item vai retornar negativa. Para comportar mais itens, será criada uma nova lista com a capacidade duplicada da atual, que será 8. Os itens da lista atual serão copiados para a nova e aí sim será adicionado o quinto item, fazendo com que ainda sobre 3 posições. Essa lógica é repetida quantas vezes forem necessárias para comportar os itens que estamos adicionando e assim vamos criando listas com capacidade de 4, 8, 16, 32, 64, 128... E as listas antigas simplesmente são deixados para trás e ficam a cargo do Garbage Collector fazer a limpeza delas. Dependendo da quantidade, isso gera pressão desnecessária no GC afetando a performance da sua aplicação. Entenderam a importância de definirmos a capacidade? Para isso, basta usar o construtor com o parâmetro int:

```
List<Aluno> alunos = new List<Aluno>(500);
```

## Conclusão
Usar a capacidade na inicialização da lista é uma abordagem extremamente simples mas muito útil ao lidar com grande quantidade dados. "Ah, mas e quando eu não sei quantos itens serão adicionados?" Aqui entra a importância de entendermos a volumetria da aplicação que estamos trabalhando. A ideia não é acertarmos a quantidade exata, mas termos uma noção para evitarmos pressão desnecessária no _Garbage Collector_. Quer entender com mais detalhes como isso funciona no GC? Confira [aqui](https://dev.to/unhacked/como-um-parametro-simples-pode-economizar-memoria-36pp)

#### Referências
[`List<T>` Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-7.0)
[Github - dotnet runtime](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs)