C#.NETCollectionsLINQTutoriel

Découvrez les tableaux, List<T>, Dictionary<TKey,TValue> et les premières opérations LINQ pour stocker, parcourir et manipuler toutes vos collections en C#.

Yva Hajatiana
15 octobre 2017
4 min de lecture
Partager :X / TwitterLinkedIn
Composition éditoriale abstraite sur les fondamentaux de C#

Collections C# : tableaux, listes et dictionnaires

Une variable stocke une valeur ; une collection en regroupe plusieurs. C# propose différentes structures selon que la taille est fixe, dynamique ou que chaque valeur doit être retrouvée par une clé.

Tableau : une taille fixe

int[] temperatures = [12, 18, 22, 25, 19];

Console.WriteLine(temperatures[0]);
Console.WriteLine(temperatures.Length);

Le premier index est 0 et le dernier Length - 1. Une fois créé, le tableau ne change pas de taille.

for (int i = 0; i < temperatures.Length; i++)
{
    Console.WriteLine($"Jour {i + 1} : {temperatures[i]} °C");
}

List<T> : une taille dynamique

List<string> courses = ["Pommes", "Pain", "Lait"];

courses.Add("Œufs");
courses.Remove("Pain");

foreach (string article in courses)
{
    Console.WriteLine(article);
}

Une liste peut grandir et rétrécir. Count donne son nombre d’éléments, tandis qu’un tableau utilise Length.

Dictionary<TKey, TValue> : accéder par clé

Dictionary<string, decimal> prix = new()
{
    ["Pomme"] = 2.50m,
    ["Banane"] = 1.80m
};

prix["Mangue"] = 4.50m;

Pour lire une clé qui peut être absente, préférez TryGetValue :

if (prix.TryGetValue("Banane", out decimal prixBanane))
{
    Console.WriteLine($"Prix : {prixBanane:C2}");
}

Un accès direct avec prix["Inconnu"] provoquerait une KeyNotFoundException.

Interroger une collection avec LINQ

LINQ permet d’exprimer un filtre, un tri ou une transformation :

List<int> nombres = [3, 7, 2, 9, 4, 11, 6];

List<int> pairsTries = nombres
    .Where(n => n % 2 == 0)
    .OrderBy(n => n)
    .ToList();

double moyenne = nombres.Average();

Les opérateurs essentiels sont :

OpérateurRôle
Wherefiltrer
Selecttransformer
OrderBytrier
Anyvérifier qu’au moins un élément correspond
Sum, Average, Min, Maxagréger

Beaucoup de requêtes LINQ utilisent l’exécution différée : elles ne parcourent réellement la source qu’au moment de l’énumération. ToList() matérialise immédiatement le résultat.

Choisir la collection

BesoinStructure
taille connue et fixetableau T[]
ajouts et suppressions fréquents en fin de séquenceList<T>
recherche d’une valeur par clé uniqueDictionary<TKey, TValue>

Projeter et regrouper avec LINQ

Select transforme chaque élément et GroupBy regroupe les éléments qui partagent une clé. Combinés, ils répondent à beaucoup de questions courantes :

List<Vente> ventes =
[
    new("Clavier", "Paris", 49.90m),
    new("Souris", "Lyon", 19.90m),
    new("Écran", "Paris", 189.00m),
    new("Clavier", "Lyon", 49.90m)
];

var totalParVille = ventes
    .GroupBy(v => v.Ville)
    .Select(g => new { Ville = g.Key, Total = g.Sum(v => v.Montant) })
    .OrderByDescending(x => x.Total);

foreach (var ligne in totalParVille)
{
    Console.WriteLine($"{ligne.Ville} : {ligne.Total} €");
}

record Vente(string Produit, string Ville, decimal Montant);

Avec Entity Framework Core, la même syntaxe LINQ est traduite en SQL : la requête s’exécute alors dans la base de données, ce qui demande quelques précautions présentées dans le guide Entity Framework Core : contrôler ses données.

Exercice : compter les mots

Écrivez un programme qui lit une phrase, puis affiche les trois mots les plus fréquents (sans tenir compte de la casse ni de la ponctuation simple) avec leur nombre d’occurrences.

Voir une solution
Console.Write("Phrase : ");
string texte = Console.ReadLine() ?? string.Empty;

char[] separateurs = [' ', ',', '.', ';', ':', '!', '?'];

var top = texte
    .ToLowerInvariant()
    .Split(separateurs, StringSplitOptions.RemoveEmptyEntries)
    .GroupBy(mot => mot)
    .Select(g => (Mot: g.Key, Nombre: g.Count()))
    .OrderByDescending(x => x.Nombre)
    .ThenBy(x => x.Mot)
    .Take(3);

foreach (var (mot, nombre) in top)
{
    Console.WriteLine($"{mot} : {nombre}");
}

Un Dictionary<string, int> alimenté dans une boucle donnerait le même résultat ; la version LINQ exprime directement l’intention : regrouper, compter, trier, garder trois.

Erreurs fréquentes

  • dépasser le dernier index d’un tableau ;
  • confondre Length et Count ;
  • lire une clé inconnue sans TryGetValue ;
  • modifier une liste pendant un foreach ;
  • enchaîner plusieurs énumérations LINQ coûteuses sans matérialiser le résultat.

Épisode précédent : les boucles en C#. Épisode suivant : créer des méthodes en C#.

La série C# pour débutants

Cette série suit une progression : chaque épisode réutilise les notions des précédents.

  1. Variables et types
  2. Saisie utilisateur et TryParse
  3. Conditions if, else et ternaire
  4. Switch et pattern matching
  5. Boucles for, while et foreach
  6. Tableaux, listes, dictionnaires et LINQ (vous êtes ici)
  7. Méthodes, paramètres et surcharges

Une fois ces bases acquises, le parcours C# et ASP.NET Core prolonge la série vers les API web, la validation et l’asynchrone.

Mots-clés :C#.NETCollectionsLINQTutoriel
Y

Yva Hajatiana

Lead développeur .NET à Paris et architecte logiciel, 10 ans d'expérience sur des SI critiques bancaires (.NET, Angular, systèmes distribués, IAM, DevOps).