1. Introdução
Trabalhar com coleções não é só percorrer, filtrar e ordenar. Muitas vezes você precisa modificar ou retrabalhar essas coleções pra que elas fiquem do jeito que você precisa: tipo pegar uma coleção de strings e transformar numa coleção de números, remover duplicatas de uma lista ou até mudar completamente a estrutura dos dados.
Dá pra resolver tudo isso usando métodos padrão das coleções, laços simples e algoritmos básicos. Pode ser um pouco mais longo do que usar LINQ, mas é totalmente transparente e ótimo pra entender como as coleções funcionam por baixo dos panos.
Principais formas de alterar coleções
Dá pra modificar coleções de vários jeitos, mas geralmente você vai precisar de uma dessas abordagens:
- Modificar o conteúdo: adicionar, remover ou trocar elementos.
- Transformar elementos: pegar a coleção original e criar uma nova — de outra estrutura, tipo ou formato (tipo transformar um List<int> em List<string>).
- Mudar a visualização: reorganizar a coleção — tipo ordenar, inverter (reverse) ou agrupar.
A gente vai focar nos dois primeiros grupos, porque ordenação já foi detalhada numa aula separada.
Coleções mutáveis e imutáveis: um detalhe importante
Lembra que algumas coleções no .NET você pode modificar à vontade (tipo List<T>), mas outras não (IReadOnlyList<T>, arrays só de leitura, etc).
- Modificação — você muda a coleção em si (tipo usando Add, Remove, Clear e por aí vai).
- Transformação — não mexe no original, cria uma coleção nova, geralmente criando uma nova lista e preenchendo ela com os elementos da coleção original.
2. Modificando o conteúdo das coleções
Todas as coleções que implementam ICollection<T> têm métodos básicos pra alterar o conteúdo. Vamos ver isso com um exemplo de catálogo de livros.
Adicionando e removendo elementos
public class Book
{
public string Titulo { get; set; }
public string Autor { get; set; }
public int Ano { get; set; }
}
List<Book> livros = new List<Book>
{
new Book { Titulo = "Código Limpo", Autor = "Robert Martin", Ano = 2008 },
new Book { Titulo = "CLR via C#", Autor = "Jeffrey Richter", Ano = 2012 }
};
// Adicionando um novo livro
livros.Add(new Book { Titulo = "Head First C#", Autor = "Andrew Stellman", Ano = 2010 });
// Removendo um livro por condição (tipo pelo autor)
for (int i = livros.Count - 1; i >= 0; i--)
{
if (livros[i].Autor == "Robert Martin")
livros.RemoveAt(i);
}
// Remover um objeto específico (se ele estiver na lista)
Book algumLivro = livros[0];
livros.Remove(algumLivro);
// Limpar toda a coleção
livros.Clear();
// Inserir um elemento numa posição específica
livros.Insert(0, new Book { Titulo = "Pro C# 9", Autor = "Andrew Troelsen", Ano = 2021 });
Substituindo e atualizando elementos
Tipo, alguém errou o ano de publicação. Como arrumar?
// Acha o livro certo no laço e corrige o ano
for (int i = 0; i < livros.Count; i++)
{
if (livros[i].Titulo == "Head First C#")
{
livros[i].Ano = 2018; // Corrigiu o ano
break;
}
}
3. Transformando coleções
Transformando o tipo dos elementos (tipo de Book pra string)
Pegar uma coleção com os títulos de todos os livros:
List<string> titulosLivros = new List<string>();
foreach (Book livro in livros)
{
titulosLivros.Add(livro.Titulo);
}
foreach (var titulo in titulosLivros)
{
Console.WriteLine(titulo);
}
Pegar os anos de todos os livros:
List<int> anosLivros = new List<int>();
foreach (Book livro in livros)
{
anosLivros.Add(livro.Ano);
}
Transformando pra um novo tipo/estrutura:
public class InfoLivroResumida
{
public string Titulo;
public int Ano;
}
List<InfoLivroResumida> infosResumidas = new List<InfoLivroResumida>();
foreach (Book livro in livros)
{
infosResumidas.Add(new InfoLivroResumida { Titulo = livro.Titulo, Ano = livro.Ano });
}
foreach (var info in infosResumidas)
{
Console.WriteLine($"{info.Titulo} ({info.Ano})");
}
Transformando coleção de coleções em uma só (flat map)
Se o livro tem uma lista de tags, pegar uma lista única com todas as tags:
public class Book
{
public string Titulo { get; set; }
public List<string> Tags { get; set; }
}
List<Book> livrosComTags = new List<Book>
{
new Book { Titulo = "Código Limpo", Tags = new List<string> { "Clean Code", "Refactoring" } },
new Book { Titulo = "CLR via C#", Tags = new List<string> { "CLR", "Internals" } }
};
List<string> todasTags = new List<string>();
foreach (var livro in livrosComTags)
{
foreach (var tag in livro.Tags)
{
todasTags.Add(tag);
}
}
foreach (string tag in todasTags)
{
Console.WriteLine(tag);
}
4. Métodos de transformação de coleções mais usados
ToArray
Pra pegar um array a partir de uma lista:
string[] arrayTitulosLivros = titulosLivros.ToArray();
Distinct — eliminando duplicatas
Autores únicos (sem LINQ):
List<string> autores = new List<string>();
foreach (Book livro in livros)
{
if (!autores.Contains(livro.Autor))
autores.Add(livro.Autor);
}
Reverse — invertendo a coleção
Pra mudar a ordem pra reversa:
livros.Reverse(); // muda na hora!
Se não quiser mexer no original:
var invertida = new List<Book>(livros);
invertida.Reverse();
Ordenação (veja a aula sobre ordenação)
livros.Sort((a, b) => a.Ano.CompareTo(b.Ano)); // ordena por ano
Agrupando por campo (imitando GroupBy)
Agrupar livros por autor (pegar um dicionário "autor — lista de livros"):
Dictionary<string, List<Book>> livrosPorAutor = new Dictionary<string, List<Book>>();
foreach (Book livro in livros)
{
if (!livrosPorAutor.ContainsKey(livro.Autor))
livrosPorAutor[livro.Autor] = new List<Book>();
livrosPorAutor[livro.Autor].Add(livro);
}
foreach (var par in livrosPorAutor)
{
Console.WriteLine($"Autor: {par.Key}");
foreach (var l in par.Value)
Console.WriteLine($" {l.Titulo}");
}
5. Dicas úteis
- Transformações usando laços funcionam sempre, em qualquer lugar.
- Pra eliminar duplicatas, usa coleções temporárias e os métodos Contains/Add.
- Não mexe na coleção enquanto percorre ela com foreach! Se precisar remover vários elementos, primeiro coloca eles numa lista separada.
6. Exemplos de tarefas comuns
Pegar a lista de livros de um ano específico
List<Book> livrosRecentes = new List<Book>();
foreach (Book livro in livros)
{
if (livro.Ano > 2010)
livrosRecentes.Add(livro);
}
foreach (var livro in livrosRecentes)
{
Console.WriteLine($"{livro.Titulo} ({livro.Ano})");
}
Mostrar todos os anos de publicação únicos em ordem crescente
List<int> anos = new List<int>();
foreach (Book livro in livros)
{
if (!anos.Contains(livro.Ano))
anos.Add(livro.Ano);
}
anos.Sort();
foreach (int ano in anos)
Console.WriteLine(ano);
Preparar livros pra exportação (criar lista-DTO)
public class LivroExportacao
{
public string Nome;
public string Escritor;
public int AnoPublicado;
}
List<LivroExportacao> livrosParaExportar = new List<LivroExportacao>();
foreach (Book livro in livros)
{
livrosParaExportar.Add(new LivroExportacao
{
Nome = livro.Titulo,
Escritor = livro.Autor,
AnoPublicado = livro.Ano
});
}
7. Erros comuns e pegadinhas
Métodos tipo Add, Remove, Clear, Insert e Sort mudam a coleção na hora.
Se você precisa de uma coleção nova — cria uma nova lista e adiciona só os elementos que quiser nela.
Pra remover elementos enquanto percorre a coleção, faz o laço de trás pra frente (for (int i = Count-1; i >= 0; i--)).
Se quiser uma lista só com elementos únicos, fica de olho nas repetições: usa Contains ou HashSet<T>.
GO TO FULL VERSION