LINQ et async/await
Ce que tu vas apprendre
- Interroger une collection avec
Where,Select,OrderByetGroupBy. - Lire et écrire une expression lambda.
- Écrire une méthode asynchrone avec
async,awaitetTask.
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.
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éthode | Rôle |
|---|---|
Where | Garde les éléments qui répondent true |
Select | Transforme chaque élément |
OrderBy | Trie par un critère |
GroupBy | Regroupe par clé |
Sum, Average | Calculent un total et une moyenne |
Any | Dit 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 :
- Une Task représente un travail en cours qui rendra un résultat plus tard.
asyncmarque une méthode qui peut attendre.awaitattend 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.
.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 :
Wherefiltre,Selecttransforme,OrderBytrie,GroupByregroupe. - Une lambda
x => expressionest une petite fonction sans nom, très utilisée avec LINQ. Sum,AverageetAnyrenvoient une valeur unique ;ToList()fabrique une liste du résultat.- Une méthode
asyncrenvoie uneTasket utiliseawaitpour attendre sans bloquer. Task.WhenAllattend plusieurs tâches lancées ensemble ; évite.Resultet.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