Le quartierC# C#Pièce 6/7Avancé

LINQ et async/await

Filtrer, trier et calculer sur des collections avec LINQ, puis écrire du code asynchrone avec Task, async et await.

Ce que tu vas apprendre

  • Interroger une collection avec Where, Select, OrderBy et GroupBy.
  • Lire et écrire une expression lambda.
  • Écrire une méthode asynchrone avec async, await et Task.

Le point de départ

Pour les exemples de ce chapitre, utilise une liste de recettes sous forme de record :

public record Recette(string Nom, string Categorie, int Minutes);

var recettes = new List<Recette>
{
    new("Crêpes", "dessert", 30),
    new("Soupe", "plat", 45),
    new("Salade", "entree", 10),
    new("Tarte", "dessert", 60)
};

LINQ (Language Integrated Query) est un ensemble de méthodes pour interroger une collection : filtrer, trier, transformer, calculer. Elles se trouvent dans l'espace de noms System.Linq, que les projets récents importent automatiquement.

Filtrer avec Where

Tu veux seulement les recettes rapides :

var rapides = recettes.Where(r => r.Minutes <= 30);

foreach (var r in rapides)
{
    Console.WriteLine(r.Nom);   // Crêpes, puis Salade
}

r => r.Minutes <= 30 est une expression lambda : une petite fonction sans nom. À gauche de la flèche, le paramètre ; à droite, le résultat. Ici, r désigne chaque recette et la lambda répond true ou false.

Trier et transformer

OrderBy trie, Select transforme chaque élément. Tu les enchaînes :

var noms = recettes
    .OrderBy(r => r.Minutes)
    .Select(r => r.Nom)
    .ToList();

// Salade, Crêpes, Soupe, Tarte

Chaque méthode renvoie un nouveau résultat, ce qui permet de les chaîner l'une après l'autre. ToList() termine en fabriquant une List.

Pour un tri décroissant, remplace OrderBy par OrderByDescending.

Une requête LINQ ne s'exécute pas quand tu l'écris, mais quand tu la parcours ou que tu appelles ToList(). On parle d'exécution différée. Pense à garder le résultat dans une liste si tu le réutilises.

Calculer et regrouper

Quelques méthodes renvoient une valeur unique :

int total = recettes.Sum(r => r.Minutes);          // 145
double moyenne = recettes.Average(r => r.Minutes); // 36.25
bool uneLongue = recettes.Any(r => r.Minutes > 50); // True

GroupBy rassemble les éléments qui partagent une clé :

var parCategorie = recettes.GroupBy(r => r.Categorie);

foreach (var groupe in parCategorie)
{
    Console.WriteLine($"{groupe.Key} : {groupe.Count()} recette(s)");
}

Chaque groupe porte sa clé dans Key et se parcourt comme une liste.

MéthodeRôle
WhereGarde les éléments qui répondent true
SelectTransforme chaque élément
OrderByTrie par un critère
GroupByRegroupe par clé
Sum, AverageCalculent un total et une moyenne
AnyDit si au moins un élément correspond

Pourquoi l'asynchrone

Certaines opérations attendent : une réponse du réseau, la lecture d'un fichier. Si le programme se bloque pendant l'attente, il ne peut rien faire d'autre. Le code asynchrone libère le programme pendant ce temps.

En C#, trois éléments vont ensemble :

  1. Une Task représente un travail en cours qui rendra un résultat plus tard.
  2. async marque une méthode qui peut attendre.
  3. await attend la fin d'une tâche sans bloquer.

Écrire une méthode asynchrone

static async Task<string> ChargerRecetteAsync(string nom)
{
    await Task.Delay(1000);   // simule une attente d'une seconde
    return $"Recette chargée : {nom}";
}

string texte = await ChargerRecetteAsync("Crêpes");
Console.WriteLine(texte);

Une méthode asynchrone renvoie une Task : Task<string> pour produire un texte, Task seule pour ne rien produire. Par convention, son nom finit par Async.

await suspend la méthode jusqu'au résultat, puis reprend avec la valeur. Pendant l'attente, le thread reste libre.

Appeler un site web

L'exemple le plus courant est une requête HTTP avec HttpClient :

using var client = new HttpClient();
string contenu = await client.GetStringAsync("https://example.com");
Console.WriteLine(contenu.Length);

GetStringAsync renvoie une Task<string>. Avec await, tu obtiens directement le texte de la page. Le mot-clé using libère le client à la fin.

Évite .Result ou .Wait() sur une tâche : ils bloquent le programme et peuvent provoquer un blocage total. Remonte plutôt async et await jusqu'à la méthode appelante.

Attendre plusieurs tâches

Pour lancer plusieurs travaux en même temps, démarre les tâches puis attends-les avec Task.WhenAll :

Task<string> a = ChargerRecetteAsync("Crêpes");
Task<string> b = ChargerRecetteAsync("Tarte");

string[] resultats = await Task.WhenAll(a, b);

Les deux chargements se déroulent en parallèle : le total dure environ une seconde, pas deux.

À retenir

  • LINQ interroge une collection : Where filtre, Select transforme, OrderBy trie, GroupBy regroupe.
  • Une lambda x => expression est une petite fonction sans nom, très utilisée avec LINQ.
  • Sum, Average et Any renvoient une valeur unique ; ToList() fabrique une liste du résultat.
  • Une méthode async renvoie une Task et utilise await pour attendre sans bloquer.
  • Task.WhenAll attend plusieurs tâches lancées ensemble ; évite .Result et .Wait().

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
Le quartier
Appartement
C#
Pièce
6/7
Plan n°
csharp/06.linq-et-async
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.