TOC

This article has been localized into Portuguese by the community.

Coleções:

Listas

C# tem um intervalo de classes para lidar com listas. Eles implementam a interface IList e a implementação mais popular é a lista genérica, muitas vezes referida como List<T>. O T especifica o tipo de objetos contidos na lista, que tem o benefício adicional que o compilador irá verificar e garantir que você adicione apenas objetos do tipo correto à lista - em outras palavras, a List<T> é tipo seguro.

List é muito parecido com a classe ArrayList, que era a opção de lista de acesso antes de listas genéricas compatíveis com C#. Portanto, você também verá que o List pode fazer muitas das mesmas coisas que um Array (que também implementa a interface IList), mas em muitas situações, List é mais simples e fácil trabalhar. Por exemplo, você não precisa criar uma lista com um tamanho específico; em vez disso, basta criá-la e o .NET a expandirá automaticamente para se ajustar à quantidade de itens à medida que você os adiciona.

Como mencionado, o T significa tipo e é usado para especificar o tipo de objetos que você deseja que a lista contenha. Em nosso primeiro exemplo, mostrarei como criar uma lista que deve conter strings:

List<string> listOfStrings = new List<string>();

Isso cria uma lista vazia, mas adicionar coisas a ela depois é muito fácil com o método Adicionar :

listOfStrings.Add("a string");

No entanto, se você tentar adicionar algo que não seja uma string, o compilador irá imediatamente reclamar sobre isso:

listOfStrings.Add(2);
Error   CS1503  Argument 1: cannot convert from 'int' to 'string'

Inicializando uma lista com itens

No exemplo acima, acabamos de criar uma lista e adicionamos um item a ela. No entanto, C # realmente permite que você crie uma lista e adicione itens a ela dentro da mesma instrução, usando uma técnica chamada inicializadores de coleção. Vamos ver como isso é feito:

List<string> listOfNames = new List<string>()
{
    "John Doe",
    "Jane Doe",
    "Joe Doe"
};

A sintaxe é bem simples: antes do ponto-e-vírgula final comum, temos um conjunto de chaves, que por sua vez contém uma lista dos valores que queremos estar presentes na lista desde o início. Como esta é uma lista de strings, os objetos iniciais que fornecemos devem ser, obviamente, do tipo string. No entanto, exatamente o mesmo pode ser feito para uma lista de outros tipos, mesmo se estivermos usando nossas próprias classes, como demonstrarei no próximo exemplo.

Trabalhando com os itens

Existem várias maneiras de trabalhar com os itens de uma lista genérica e para mostrar alguns deles, criei um exemplo maior:

using System;
using System.Collections.Generic;

namespace Lists
{
    class Program
    {
static void Main(string[] args)
{
    List<User> listOfUsers = new List<User>()
    {
new User() { Name = "John Doe", Age = 42 },
new User() { Name = "Jane Doe", Age = 34 },
new User() { Name = "Joe Doe", Age = 8 },
    };

    for(int i = 0; i < listOfUsers.Count; i++)
    {
Console.WriteLine(listOfUsers[i].Name + " is " + listOfUsers[i].Age + " years old");
    }
    Console.ReadKey();
}
    }

    class User
    {
public string Name { get; set; }

public int Age { get; set; }
    }
}

Vamos começar de baixo, onde definimos uma classe simples para armazenar informações sobre um usuário - apenas um nome e uma idade. Voltar para a parte superior do exemplo, onde mudei nossa lista para usar essa classe de usuário em vez de strings simples. Eu uso um inicializador de coleção para preencher a lista com os usuários - observe como a sintaxe é a mesma de antes, apenas um pouco mais complexa, porque estamos lidando com um objeto mais complexo do que com uma string.

Quando tivermos a lista pronta, eu uso um loop for para executá-la - para saber quantas iterações vamos fazer, eu uso a propriedade Count do Lista. Em cada iteração, acesso o usuário em questão por meio do indexador da lista, usando a sintaxe de colchetes (por exemplo, listOfUsers [i]). Uma vez que eu tenho o usuário, eu saída nome e idade.

Adicionando, Inserindo & Removendo itens

Já tentamos adicionar um único item a uma lista, mas há mais opções para isso. Primeiro de tudo, você pode inserir um item em vez de adicioná-lo - a diferença é que, enquanto o método Adicionar sempre adiciona ao final da lista, o método Inserir permite que você para inserir um item em uma posição específica. Aqui está um exemplo:

List<string> listOfNames = new List<string>()
{
    "Joe Doe"
};
// Insert at the top (index 0)
listOfNames.Insert(0, "John Doe");
// Insert in the middle (index 1)
listOfNames.Insert(1, "Jane Doe");

Começamos a lista com apenas um item, mas depois inserimos mais dois itens, primeiro no topo da lista e depois no meio. O primeiro parâmetro do método Insert é o índice em que queremos inserir o item. Tenha cuidado, porém - uma exceção será lançada se você tentar inserir um item no índice 3, se a lista tiver menos itens!

Adicionando vários itens

Assim como temos os métodos Adicionar e Inserir para adicionar um único item, também há métodos correspondentes para adicionar e inserir vários itens. Eles são chamados de AddRange() e InsertRange() e aceitam qualquer tipo de coleção que implemente o IEnumerable como um parâmetro - ele poderia ser por exemplo uma matriz de itens ou outra lista, quais itens você deseja adicionar ou inserir na lista atual.

Como um exemplo nos métodos Range, vamos fazer algo divertido - combinamos o método AddRange com um inicializador de coleção para adicionar vários novos nomes a uma lista existente em uma única instrução:

listOfNames.AddRange(new string[]
    {
"Jenna Doe",
"Another Doe"
    });

Nós simplesmente criamos uma matriz de strings on-the-fly e imediatamente anexamos seus itens à nossa lista de nomes do exemplo anterior.

Removendo itens

Existem atualmente três métodos à sua disposição quando você deseja remover um ou vários itens de uma lista: Remove() , RemoveAt() e RemoveAll() .

O método Remove() usa apenas um parâmetro: o item que você deseja remover. Isso é ótimo para, e. uma lista de strings ou inteiros, porque você pode simplesmente escrever o item que deseja remover. Por outro lado, se você tem uma lista de objetos complexos, você teria que encontrar esse objeto primeiro, para ter uma referência que você poderia passar para o método Remove(). Vamos lidar com isso mais tarde - aqui está um exemplo muito básico como você pode remover um único item com o método Remove():

List<string> listOfNames = new List<string>()
{
    "John Doe",
    "Jane Doe",
    "Joe Doe",
    "Another Doe"
};

listOfNames.Remove("Joe Doe");

O método Remove() simplesmente percorre a lista até encontrar a primeira instância do objeto que você especificou para remoção, e ele remove-a - apenas remove uma instância e, se você especificar um item na lista que não existe, nenhum erro é lançado. O método retorna verdadeiro se ele foi capaz de remover um item e falso se não foi.

O método RemoveAt() aproveita o fato de que a lista genérica é baseada em índice, permitindo que você remova um item com base em seu índice/posição na lista. Por exemplo, você poderia remover o primeiro item da lista assim:

listOfNames.RemoveAt(0);

Ou o último item da lista como este:

listOfNames.RemoveAt(listOfNames.Count - 1);

Novamente, isso só remove um único item e, desta vez, você deve ter cuidado ao fornecer o índice do item a ser removido - se você usar um índice que esteja fora dos limites (menor que 0 ou maior que a quantidade de itens), exceção será lançada! Portanto, a menos que você tenha certeza do que está fazendo, talvez queira incluir o método RemoveAt() em um bloco try-catch para manipular a exceção (explicado em detalhes em outro lugar neste tutorial). O método RemoveAt() não retorna nada, então você terá que verificar a quantidade de itens na lista antes e depois da chamada, para decidir se ela foi bem sucedida - por outro lado, se você sabe que tem um índice que existe na lista, que você deve sempre ter certeza, então você sempre pode esperar que RemoveAt() seja bem-sucedido.

O RemoveAll() é o mais complexo dos métodos remove, mas definitivamente também é o mais poderoso. Ele leva um delegado para um método como seu parâmetro e esse método decide se um item deve ser removido ou não, retornando true ou false. Isso permite que você aplique sua própria lógica ao remover itens e também permite remover mais de um item de cada vez. Delegados serão tratados em outro lugar neste tutorial, porque é um assunto grande e complexo, mas eu ainda quero que você tenha uma noção de como o método RemoveAll é legal, então aqui está um exemplo:

List<string> listOfNames = new List<string>()
{
    "John Doe",
    "Jane Doe",
    "Joe Doe",
    "Another Doe"
};

listOfNames.RemoveAll(name =>
{
    if (name.StartsWith("J"))
return true;
    else
return false;
});

Neste exemplo, usamos um método anônimo (novamente complexo demais para ser explicado aqui, mas será tratado em outro capítulo) como um parâmetro para o método RemoveAll. Nosso método anônimo é bastante simples - ele será chamado para cada item na lista e terá um parâmetro chamado nome , que é, obviamente, o item atual na iteração. Ele olha para este nome e se começar com "J", o true é retornado - caso contrário, false . O método RemoveAll() usa essa resposta (true ou false) para decidir se cada item deve ser removido ou não. No final, isso deixa a nossa lista inicial com apenas um membro Doe: Another Doe.

Ordenar itens da lista

Até agora, os itens da lista com os quais trabalhamos acabaram de ser usados na ordem em que foram adicionados à lista. No entanto, você pode querer que os itens sejam classificados de uma maneira específica, por exemplo, Alfabeticamente, no caso de nossa lista de nomes. A lista & lt; T & gt; tem um método Sort() que podemos usar para isso:

List<string> listOfNames = new List<string>()
{
    "John Doe",
    "Jane Doe",
    "Joe Doe",
    "Another Doe"
};
listOfNames.Sort();
foreach (string name in listOfNames)
    Console.WriteLine(name);

Como você verá na saída, os itens na lista foram classificados em ordem alfabética, e se você quiser em ordem decrescente (de Z para A), simplesmente chame o método Reverse() após você executa o tipo:

listOfNames.Sort();
listOfNames.Reverse();

Então, classificar uma lista foi bem fácil, certo? Bem, foi principalmente tão fácil porque temos uma lista de strings e o .NET framework sabe exatamente como comparar duas strings. Se você tiver uma lista de números, o .NET também saberá como ordenar isso. Por outro lado, você pode ter uma lista de objetos personalizados (já que a Listagem pode conter qualquer objeto) que o .NET não tenha uma chance de saber como comparar. Existem várias soluções para este problema, por ex. implementando a interface IComparable ou usando o LINQ (veremos mais adiante neste tutorial), mas como uma correção rápida, podemos também fornecer um método para chamar o método Sort(), para aprender como dois itens se acumulam uns contra os outros, assim:

using System;
using System.Collections.Generic;

namespace ListSort
{
    class Program
    {
static void Main(string[] args)
{
    List<User> listOfUsers = new List<User>()
    {
new User() { Name = "John Doe", Age = 42 },
new User() { Name = "Jane Doe", Age = 39 },
new User() { Name = "Joe Doe", Age = 13 },
    };
    listOfUsers.Sort(CompareUsers);
    foreach (User user in listOfUsers)
Console.WriteLine(user.Name + ": " + user.Age + " years old");
}

public static int CompareUsers(User user1, User user2)
{
    return user1.Age.CompareTo(user2.Age);
}
    }

    public class User
    {
public string Name { get; set; }
public int Age { get; set; }
    }
}

Isso acrescentou um pouco de código ao nosso exemplo, mas na verdade não é muito complicado. Se começarmos de baixo, criei uma classe User muito simples, consistindo de um nome e uma idade. No meio, declarei um método chamado CompareUsers() - ele usa dois usuários como parâmetros e retorna um inteiro, que indica se um item é "menor", "o mesmo" ou " maior "(-1, 0 ou 1). Esses valores serão usados pelo método Sort() para mover os itens para que a ordem dos itens corresponda ao que desejamos. Nesse caso, simplesmente uso a propriedade Age para comparação, essencialmente deixando-nos com uma lista de usuários classificados por idade.

Resumo

Este artigo é um dos mais longos deste tutorial, mas espero que você tenha aprendido muito sobre listas, porque quanto mais programação você fizer, mais você perceberá quão importantes são as listas e os dicionários. Falando em dicionários, vamos discuti-los no próximo artigo.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!