TOC

This article is currently in the process of being translated into Italian (~99% done).

Collections:

Lists

C# ha una serie di classi dedicate alle liste. Sono implementate nell'interfaccia IList e l'implementazione più popolare è la lista "generic", spesso chiamata List<T>. La T spefica il tipo di oggetto contenuto dalla lista, ed ha il beneficio aggiuntivo che il compilatore controllerà per essere sicuro di aver aggiunto solamente oggetti del tipo corrente della lista - in altre parole, la lista List<T>. , è type-safe.

List<T> è molto simile alla classe ArrayList, che era la lista scelta per eccellenza prima che C# supportante le liste generic. Dunque noterai che le liste List<T> possono fare un sacco di cose uguali agli array (che a proposito implementano l'interfaccia IList), ma in molte situazioni, la lista List<T> risulta più semplice e facile da lavorarci. Per esempio, non devi creare una lista di una grandezza specifica - al suo posto, devi semplicemente crearla e .NET ne aumenterà autonomamente le dimensioni per farci stare gli oggetti mentre gli aggiungi.

Come abbiamo menzionato, la T è il tipo e d è utilizzata per specificare che tipo di oggetto vuoi che la lista contenga. Nel nostro primo esempio, ti mostrerò come creare una lista contenente stringhe:

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

Questo crea una lista vuota, ma aggiungerne oggetti all'interno è molto semplice utilizzando il metodo Add.

listOfStrings.Add("a string");

Adesso se si prova ad aggiungere qualsiasi cosa che non sia una stringa, il compilatore si lamenterà immediatamente:

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

Inizializzare una lista con oggetti

Nell'esempio qui sopra, abbiamo creato una lista e poi abbiamo aggiunto un elemento. Comunque, C# permette di creare una lista e aggiungere elementi con la stessa dichiarazione, usando una tecnica chiamata collection initializers. Vediamo com'è fatta:

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

La sintassi è abbastanza semplice: Prima del punto e virgola finale basta aggiungere una coppia di parentesi graffe, che conterranno una lista dei valori vogliamo inserire nella lista sin dall'inizio. Dato che si tratta di una lista di stringhe, l'oggetto iniziale che forniamo deve essere di tipo stringa. Questo può essere compiuto per liste di altri tipi, anche se stiamo utilizzando la nostra classe personale, lo dimostreremo nel prossimo esempio.

Lavorare con gli oggetti

Ci sono molti modi per lavorare con gli oggetti di una lista generica e per mostrartene alcuni, creerò un esempio piu grande:

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; }
    }
}

Iniziamo dal fondo, dove definiamo la classe che tiene le informazioni su User - semplicemente un nome e l'età. Tornando in cima, dove ho modificato la lista per utilizzare la classe User invece di semplici stringhe. Ho utilizzato l'inizializzatore per popolare la lista con utenti (Users) - Nota come la sintassi è la stessa di prima, leggermente piu complessa perchè stiamo lavorando con oggetti piu complessi di stringhe.

Non appena abbiamo la lista pronta, utilizzo il ciclo for per ciclare attraverso la lista - per sapere quante iterazioni dobbiamo fare utilizzo la proprietà Count della lista. In ogni singola iterazione, accedo all'User in questione attraverso l'indicizzatore della lista, utilizzando le parentesi graffe (esempio listOfUsers[i]). Una volta ottenuto l'utente (User), mando in uscita nome e età.

Aggiungere, Infilare e Rimuovere oggetti

Abbiamo già provato ad aggiungere oggetti singoli alla lista, però abbiamo piu modi per farlo. Per prima cosa, puoi inserire oggetti invece che aggiungerli - la differenza è semplice, il metodo Add aggiunge sempre alla fine della lista, mentre il metodo Insert(Inserimento) ti permette di inserirlo in una specifica posizione. Ecco un esempio:

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");

Iniziamo la lista con un solo oggetto, dopodiche ne inseriamo altri due, il primo in cima alla lista, il secondo al centro. il primo parametro del metodo Insert è l'indice di dove vogliamo inserire l'oggetto. Fai attenzione - riceverai un errore del compilatore se provi ad inserire un oggetto in posizione 3 se la lista possiede meno oggetti!

Aggiungere più oggetti

Esattamente come abbiamo i metodi Add e Insert per aggiungere oggetti singoli, abbiamo dei metodi corrispondenti per aggiungerne multipli. Sono chiamati AddRange() e InsertRange() ed accettano qualsiasi tipo di collezzione che implementa l'interfaccia IEnumerable come parametro - Questo potrebbe essere, ad esempio, un array di oggetti o un altra lista, di cui vuoi che gli oggetti vengano inseriti nella lista corrente.

Come esempio per la serie di metodi, facciamo qualcosa di divertente - Combiniamo il metodo AddRange con l'inizializzatore della collezione per aggiungere più nomi in una lista già esistente utilizzando un singolo comando:

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

Basta creare un array di stringhe al volo ed aggiungerne gli oggetti alla lista di nomi del precedente esempio.

Rimuovere oggetti

Ci sono tre metodi per poter rimuovere uno o più oggetti da una lista: Remove(), RemoveAt() e RemoveAll().

Il metodo Remove() prendere un singolo parametro : L'oggetto che vuoi rimuovere. Questo è ottimo per, esempio, una lista di stringhe o numeri interi, perchè puoi semplicemente scrivere l'oggetto che vuoi rimuovere. D'altro canto, se hai una lista di oggetti complessi, devi per prima cosa trovare l'oggetto, per averne un riferimento se poter passare al metodo Remove(). Di seguito un esempio molto semplice su come si può rimuovere un singolo oggetto con il metodo Remove():

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

listOfNames.Remove("Joe Doe");

Il metodo Remove() semplicemente cicla attraverso la lista finchè non trova il primo oggetto che hai specificato da rimuovere, dopodichè lo rimuove - Ne rimuove solo una copia, e se richiedi un oggetto nella lista che non esiste, non riceverai messaggi di errore. Il metodo restituisce valore positivo (true) se è in grado di rimuovere l'oggetto e negativo (false) in caso contrario.

Il metodo RemoveAt() prende vantaggio del fatto che le liste generiche sono basate su indici, permettendoti di rimuovere oggetti a seconda del indice/posizione nella lista. Per esempio, puoi rimuovere il primo oggetto di una lista in questo modo:

listOfNames.RemoveAt(0);

Oppure l'ultimo oggetto della lista così:

listOfNames.RemoveAt(listOfNames.Count - 1);

Dinuovo, questo rimuove solamente un oggetto alla volta, devi fare attenzione quando fornisci l'indice dell'oggetto da rimuovere - se usi un indice che va fuori portata (meno di 0 o maggiore del numero degli oggetti della lista) riceverai un messaggio d'errore! Quindi, a meno che non sei sicuro di cosa stai facendo, probabilmente preferiresti utilizzare il metodo RemoveAt() in un blocco try-catch per trattare l'errore. Il metodo RemoveAt() non ritorna nessun valore, quindi dovrai controllare il numero di oggetti nella lista prima e dopo averlo eseguito, per controllare se ha avuto successo - D'altro canto, se sai di avere un indice esistente nella lista, puoi aspettarti che il metodo RemoveAt() abbia successo.

Il metodo RemoveAll() è il metodo più complesso, ma decisamente anche il più potente. Prende un delegato o un metodo come parametro che ha il compito di decidere se un oggetto deve essere rimosso oppure no, restituendo il valore vero (true) o falso (false). Questo ti permette di applicare una tua logica quando si rimuovono oggetti, inoltre ti permette di rimuovere più di un oggetto alla volta. I delegati verranno trattati altrove in questo tutorial, in quanto si tratta di un argomento vasto e complesso, ma voglio comunque farti vedere quanto sia fantastico il metodo RemoveAll, ecco un esempio:

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;
});

In questo esempio, utilizziamo un altro metodo anonimo (troppo completto per essere spiegato qui, lo tratteremo in un altro capitolo) come parametro per il metodo RemoveAll. Il nostro metodo anonimo è abbastanza semplice - verrà chiamato per ogni singolo oggetto della lista, chiamando il parametro name, che naturalmente è l'oggetto del ciclo corrente. Controllerà se il nome (name) e se inizia con la lettera "J", ritorna il valore true(vero) - altrimenti false(falso). Il metodo RemoveAll utilizza la risposta (vero o falso) per decidere se l'oggetto deve essere rimosso oppure no. Alla fine, questo lascia la nostra lista iniziale con solo un membro rimanente: Another Doe.

Riordinare la lista di oggetti

Finora gli oggetti della lista sono stati utilizzati nell' ordine in cui li abbiamo aggiunti. Tuttavia, potresti voler ordinare la lista di oggetti in un modo specifico, per esempio in ordine alfabetico nel caso della nostra lista di nomi. List<T> ha il metodo Sort() che può essere usato per questo:

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

Come vuoi vedere dall' uscita, gli oggetti della lista sono stati riordinati alfabeticamente, e se li vuoi ordinare in ordine decrescente (dalla Z alla A), basta semplicemente utilizzare il metodo Reverse() subito dopo il riordine:

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

Riordinare la lista è abbastanza semplice, vero? Questo perchè abbiamo una lista di stringhe e il .NET framework sà esattamente come confrontare due stringhe. Se hai una lista di numeri, il .NET saprà, ovviamente, come ordinare anche quello. D'altro canto, potresti avere una lista di oggetti personalizzati ( dato che la lista List<T> può contenere qualunque oggetto) e il .NET non ha possibilità di sapere come confrontarli. Ci sono diverse soluzioni a questo problema, ad esempio implementando l'interfaccia ICompare oppure utilizzando LINQ (vedremo entrambi piu avanti nel tutorial), ma come soluzione veloce, possiamo anche fornire un metodo da chiamare per il metodo Sort(), per imparare come due oggeti si comparano l'un l'altro come nel esempio seguente:

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; }
    }
}

Questo ha aggiunto parecchio codice al nostro esempio, ma non si tratta di nulla troppo complicato. Se partiamo dal fondo, ho creato una semplice classe User, che consiste in un nome (name) e l'età (age). Al centro ho dichiarato il metodo CompareUsers() - prende due parametri User come parametro e ritorna una variabile intera, che indica se un oggetto è piu piccolo, stessa dimensione o piu grande (-1,0,1). Questi valori saranno utilizzati dal metodo Sort() per muovere gli oggetti in modo che l'ordine degli oggeti corrisponderà a quello che vogliamo. Nel nostro esempio, voglio confrontare semplicemente l'età (age), lasciandoci con una lista di utenti (User) ordinati per età.

Sommario

Questo articolo è uno dei più lunghi di questo tutorial, spero che tu abbia imparato un sacco sulle liste, perchè più programmi più ti accorgerai quanto le liste e i dizionari siano importanti. Parlando di dizionari, li discuteremo nel prossimo articolo.

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!