1. Introduction
Vous ne le saviez peut‑être pas, mais l'une des questions préférées en entretien — « Qu'est‑ce que vous savez des expressions lambda ? ». Pourquoi on les demande ? Parce que c'est un truc super pratique et "à la mode" en C#, qui permet d'écrire moins de code et de le rendre plus expressif. Si les méthodes anonymes, c'est comme écrire une lettre à la main, les expressions lambda, c'est comme envoyer un message dans un messenger : rapide, compact, et parfois même avec des emojis (bon, presque).
Les expressions lambda sont arrivées en C# depuis la version 3.0 et depuis elles se sont répandues partout : dans LINQ, les gestionnaires d'événements, les threads, les collections et même les bibliothèques d'IA sur .NET.
Une expression lambda est une façon de déclarer une méthode directement dans le corps du code, "sur place", sans nom, super courte et claire. La syntaxe de base ressemble toujours à ceci :
(paramètres) => expression_ou_bloc_de_code
Ce "chevauchement" => s'appelle « opérateur lambda » ou « flèche ».
Petite analogie
Souvenez‑vous quand vous écrivez une recette : « Prendre une pomme, la couper, la mettre dans un bol ».
En C# ça serait :
(pomme) => couper(pomme)
2. Transformer une méthode anonyme en lambda
Supposons qu'on a un delegate :
delegate int SquareDelegate(int x);
La méthode anonyme ressemblerait à ceci :
SquareDelegate sq = delegate(int x) {
return x * x;
};
Et maintenant la même chose avec une expression lambda :
SquareDelegate sq = (int x) => { return x * x; };
Mais C# peut inférer les types, et on peut encore raccourcir :
SquareDelegate sq = x => x * x;
Quelle compacité impressionnante !
Comparaison avec une méthode "normale" et une fonction anonyme
| Méthode | Déclaration | Où utiliser | Inconvénients |
|---|---|---|---|
| Méthode nommée | Dans une classe | Partout | Besoin d'un nom, plus de code |
| Méthode anonyme | Dans le code | Seulement avec des delegates | Syntaxe plus verbeuse |
| Expression lambda | Dans le code | Partout avec des delegates | Parfois le type n'est pas évident |
3. Syntaxe des expressions lambda : variantes
Paramètres
Sans paramètres :
Action hello = () => Console.WriteLine("Bonjour, monde !");
Un paramètre (les parenthèses peuvent être omises) :
Func<int, int> inc = x => x + 1;
Plusieurs paramètres (les parenthèses sont nécessaires) :
Func<int, int, int> sum = (a, b) => a + b;
Corps de la lambda
Une expression — sans accolades et sans return :
x => x * x
Bloc de code — accolades, return requis :
(x, y) =>
{
int z = x + y;
return z * z;
}
Types des paramètres
La plupart du temps il n'est pas nécessaire d'indiquer le type — le compilateur l'inférera. Mais si vous voulez, allez-y :
(x, y) => x + y // Le compilateur infère les types.
(int x, int y) => x + y // On peut les préciser explicitement.
4. Nuances et exemples plus réels
Utilisation avec des collections
Souvenez‑vous de notre mini‑appli pédagogique (par exemple, une liste d'utilisateurs) ? Supposons qu'on a un tableau de nombres :
int[] numbers = { 1, 2, 3, 4, 5 };
On veut sélectionner uniquement les nombres pairs :
var evenNumbers = numbers.Where(n => n % 2 == 0);
Ici Where est une méthode d'extension LINQ, et la condition est notre filtre lambda.
Passage en paramètre à une méthode
Supposons qu'on a un delegate méthode :
public delegate bool Filter(int number);
public static int[] FilterNumbers(int[] data, Filter predicate)
{
var result = new List<int>();
foreach (var n in data)
if (predicate(n))
result.Add(n);
return result.ToArray();
}
On passe maintenant une expression lambda :
int[] evens = FilterNumbers(numbers, n => n % 2 == 0);
Lambda comme gestionnaire d'événements
button.Click += (sender, args) => Console.WriteLine("Le bouton a été cliqué !");
5. Expressions lambda et delegates génériques standard
Il est difficile d'imaginer les lambdas sans Func<>, Action<> et Predicate<>. Ce sont des types de delegate pratiques :
- Action — ne retourne rien.
- Func — retourne une valeur.
- Predicate — retourne un bool, généralement pour filtrer.
Exemple avec Action :
Action<string> log = message => Console.WriteLine(message);
log("Ce message via lambda !");
Exemple avec Func :
Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15
Exemple avec Predicate :
Predicate<int> isNegative = n => n < 0;
bool test = isNegative(-7); // true
6. Lambdas avec plusieurs expressions : quand utiliser un bloc
Si une lambda doit effectuer plusieurs opérations, utilisez des accolades et un return explicite :
Func<int, int, string> describeSum = (a, b) =>
{
int sum = a + b;
return $"Somme : {sum}";
};
Sans return le compilateur protestera (mais n'expliquera pas toujours clairement pourquoi — il dira juste que "tous les chemins ne retournent pas une valeur").
7. Retour void : Action
Quand la lambda ne retourne rien, utilisez Action :
Action greet = () => Console.WriteLine("Souriez — le code compile !");
Une lambda peut contenir autant d'instructions que nécessaire :
Action<int> printSquare = x =>
{
int sq = x * x;
Console.WriteLine($"Le carré de {x} est {sq}");
};
8. Limitations et erreurs typiques
Parfois on a envie d'écrire une lambda très librement, mais le compilateur n'est pas toujours d'accord.
On ne peut pas déclarer une variable ayant le même nom qu'une variable capturée depuis l'extérieur.
Faites attention aux types : si la signature du delegate et de la lambda ne correspondent pas — erreur.
Le retour d'une valeur est obligatoire si le delegate attend une valeur de retour.
Dans les lambdas complexes, n'oubliez pas les accolades. Une expression — pas d'accolades ni de return. Plusieurs instructions — accolades et return.
GO TO FULL VERSION