Collections

Une liste, ou List<T>, est une structure de données générique et séquentielle. Le type spécifique qu’elle contient est défini lors de son instanciation.

Les listes ont plusieurs avantages par rapport aux arrays :

  • Elles ont une longueur pratiquement illimitée ;
  • Elles gardent automatiquement une trace du nombre d’éléments dans la liste ;
  • Elles possèdent des méthodes pour travailler avec plusieurs éléments d’un coup.

Les arrays sont plus rapides si elles ont une longueur prédéterminées. Mais les listes sont meilleures lorsque ce nombre est inconnus.

Pour utiliser des listes et dictionnaires dans notre code il faut inclure le namespace suivant :

using System.Collections.Generic;

Listes

Créer une liste

// Instanciation d'une liste vide avec des ()
List<string> citiesList = new List<string>(); // Liste de strings
List<Object> objects = new List<Object>(); // Liste d'objets génériques

// Initialisation d'objets avec des {}
List<string> citiesList = new List<string> { "Rome", "Madrid", "Paris" };

Ajouter des éléments

Ajouter un élément à la liste se fait grâce à la méthode .Add() :

// Ajout d'un élément dans la liste déjà créée
citiesList.Add("Delhi");

Supprimer des éléments

Supprimer un élément d’une liste se fait grâce à la méthode .Remove() :

bool success = citiesList.Remove("Delhi");
// Si la valeur est dans la liste, success sera à True, sinon à False

Il est également possible de vider totalement une liste avec .Clear() :

List<string> citiesList = new List<string> { "Delhi", "Los Angeles", "Kyiv" };
citiesList.Clear();

Console.WriteLine(citiesList.Count);
// Output: 0

Accéder à des éléments

Cela s’effectue comme pour les arrays, avec un crochet pour rechercher une valeur par son index.

string city = citiesList[0]

Il est ensuite possible de réassigner des éléments :

citiesList[0] = "New Delhi";

Compter le nombre d’éléments d’une liste

Identifier le nombre d’éléments avec Count :

List<string> citiesList = new List<string> { "Delhi", "Los Angeles" };
int numberCities = citiesList.Count;
// numberCities is 2

Rechercher dans une liste

Identifier si un élément existe dans la liste avec Contains() :

bool hasDelhi = citiesList.Contains("Delhi");
bool hasDubai = citiesList.Contains("Dubai");
// hasDelhi is true, hasDubai is false

Rechercher des valeurs dans une liste avec Find() :

var integers = new List<int> { 1, 2 ,3 ,4 ,5 };
var item = integers.Find(x => x == 3)

Travailler avec des plages (ranges)

AddRange() : prend un tableau ou une liste en argument. Ajoute les valeurs à la fin de la liste. Ne retourne rien.

InsertRange() : prend un entier et un tableau ou une liste en argument. Ajoute les valeurs à l’index spécifié par l’entier. Ne retourne rien.

RemoveRange() : prend deux entiers. Le premier entier est l’index à partir duquel commencer la suppression, et le second est le nombre d’éléments à supprimer. Ne retourne rien.

GetRange() : prend deux entiers. Le premier est l’index du premier élément souhaité, et le second est le nombre d’éléments dans la plage souhaitée. Retourne une liste du même type.

List<string> places = new List<string> { "first", "second" };

places.AddRange(new string[] { "fifth", "sixth" });
// List is  "first", "second", "fifth", "sixth" ]
places.InsertRange(2, new string[] { "third", "fourth"});
// List is [ "first", "second", "third", "fourth", "fifth", "sixth" ]
places.RemoveRange(4, 2);
// List is [ "first", "second", "third", "fourth" ]
List<string> newPlaces = places.GetRange(0, 3);
// New list is [ "first", "second", "third" ]

Dictionnaires

Un dictionnaire permet de stocker des paires clé-valeur.

[!warning] La clé et la valeur peuvent être de types différents (ex. int -> string)

Création d’un dictionnaire

Les clés n’ont pas besoin d’être séquentielles, on peut leur attribuer des valeurs arbitraires. Il faut cependant pas que deux valeurs aient la même clé.

Dictionary<int, string> monDico = new Dictionary<int, string>();
monDico[1] = "Pomme";
monDico[2] = "Poire";
monDico[1] = "Abricot"; // Erreur car "1" existe déjà

Recherche d’une valeur

if (monDico.TryGetValue(2, out string valeur)) {
    Console.WriteLine("Valeur : " + valeur);
}
else {
    Console.WriteLine("Clé non trouvée");
}

Hashtables

Un hashtable est une structure de données non générique optimisée pour la performance brute.

var table = new Hashtable
{
	{ 0, "Charles Dickens" },
	{ 1, "George Orwell" },
	{ 2, "Mark Twain" },
	{ 3, "Jane Austen" }
}

foreach(DictionaryEntry entry in table) {
	Console.WriteLine($"{entry.key} : {entry.Value}");
}

Queue vs Stack

Ces termes définissent l’ordre des données dans des collections entre :

  • FIFO (First In, First Out) : premier arrivé -> premier servi
  • LIFO (Last In, First Out) : dernier arrivé -> premier servi

Ces notions sont essentielles dans certains cas de figure où l’ordre est crucial (file de messages, historique, navigation etc.)

Queue : file d’attente (FIFO)

Ajouter un élément : Enqueue(objet) Retirer et retourner l’élément en tête : Dequeue()

var queue = new Queue<int>();

// Ajouter des éléments
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);

// Retirer des éléments
while (file.Count > 0) {
    Console.WriteLine(file.Dequeue());  // Affiche : 1, puis 2, puis 3
}

Stack : pile (LIFO)

Ajouter un élément : Push(objet) Retirer et retourner l’élément en tête : Pop()

var stack = new Stack<int>();

// Ajouter des éléments
stack.Push(1);
stack.Push(2);
stack.Push(3);

// Retirer les éléments
while (stack.Count > 0) {
    Console.WriteLine(stack.Pop());  // Affiche : 3, puis 2, puis 1
}