CodeGym /Cours /C# SELF /Filtrer des données avec Where

Filtrer des données avec Where

C# SELF
Niveau 31, Leçon 2
Disponible

1. Intro

Filtrer, c’est prendre dans une collection seulement les éléments qui remplissent une certaine condition. Imagine : t’as 10 000 produits dans ta base, et le manager veut « juste » 12 qui matchent un nouveau critère tordu. Écrire à chaque fois une boucle et plein de checks à la main, c’est pas fun, et ton code devient vite illisible. LINQ fait tout ça pour toi.

Dans les applis réelles, filtrer c’est l’opération la plus courante : on montre à l’utilisateur que les enregistrements qui l’intéressent, on « nettoie » la collection des éléments indésirables, on fait des sélections pour des rapports, des recherches ou des envois d’e-mails. En entretien, les questions sur le filtrage LINQ tombent tout le temps. Comprendre ce sujet, c’est la base pour un dev .NET débutant.

2. On découvre la méthode Where

Le sens et le principe

La méthode Where c’est une méthode d’extension LINQ qui prend une fonction (ou une lambda) qui définit la condition de filtrage. Elle renvoie une nouvelle séquence (sans toucher à l’originale !), qui contient seulement les éléments pour lesquels la condition renvoie true.

Signature de base :

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate)

T’inquiète pas pour les generics et les mots chelous. Ce qui compte ici : Where prend ta collection de base et la condition que tu veux. En vrai, c’est simple :

  • source — la collection à filtrer (genre List<Product>)
  • predicate — la fonction/condition (genre p => p.Price > 100)

Un petit exo pour commencer

Imaginons qu’on a une liste de produits, et on veut juste ceux qui coûtent plus de 100. À l’ancienne, on aurait fait une boucle foreach et ajouté à la main les bons éléments dans une nouvelle liste. Avec LINQ, c’est une seule ligne.

3. Filtrage

Notre classe Product et la collection de départ

Dans le module d’avant, on avait écrit une classe produit comme ça :


class Product
{
    public string Name { get; set; }
    public double Price { get; set; }

    // Pour un affichage stylé :
    public override string ToString()
    {
        return $"{Name} (prix : {Price})";
    }
}

Imaginons qu’on a une liste de produits :


var products = new List<Product>
{
    new Product { Name = "Pain", Price = 30 },
    new Product { Name = "Lait", Price = 87 },
    new Product { Name = "Fromage", Price = 250 },
    new Product { Name = "Chocolat", Price = 130 }
};

Filtrer les produits à plus de 100 avec Where


var expensiveProducts = products.Where(p => p.Price > 100);

foreach (var product in expensiveProducts)
{
    Console.WriteLine(product);
}

Ce qui se passe sous le capot :

  • Where parcourt tous les éléments de products,
  • Pour chaque, il appelle la fonction (ici : p => p.Price > 100),
  • Si la fonction renvoie true, le produit va dans la nouvelle collection.

Résultat à l’écran :

Fromage (prix : 250)
Chocolat (prix : 130)

À noter : la liste d’origine products n’a pas bougé ! LINQ ne casse pas tes données.

4. Filtrage paresseux (Deferred Execution)

Un truc important : le résultat de Where est calculé seulement quand tu utilises vraiment les éléments. Genre, dès que tu lances la boucle foreach, LINQ « va » dans la collection de base et filtre à la volée. Si tu n’utilises pas le résultat, rien ne se passe. Ça s’appelle exécution différée (deferred execution).

Ça donne plein d’avantages :

  • Tu peux faire des chaînes de méthodes super longues (genre filtrer puis trier), et tout ne s’exécute qu’au premier vrai accès au résultat.
  • Économie de mémoire : pas de collections intermédiaires inutiles.
  • Tu peux annuler ou « stopper » après avoir trouvé assez d’éléments.

Schéma visuel


Collection de base       —►   Where (condition)    —►   On parcourt que les bons éléments
    
[ x ] [ x ] [ + ] [ + ]  —►   p.Price > 100      —►   [ + ] [ + ]

(x — l’élément ne passe pas la condition, + — il passe)

5. Variantes de syntaxe

Syntaxe méthode classique (Method Syntax)

C’est le style qu’on utilise déjà :

var result = products.Where(p => p.Price > 100);

Alternative : Query Syntax

LINQ supporte une syntaxe qui ressemble aux requêtes SQL :


var result = from p in products
             where p.Price > 100
             select p;

Le résultat est le même !
Le choix de la syntaxe, c’est une question de goût, mais la method syntax (avec les points) est plus courante, surtout dans les vrais projets et pour les chaînes longues.

6. Conditions de filtrage complexes

Plusieurs conditions

Tu peux utiliser les opérateurs logiques (&&, ||, !) :


// Trouver tous les produits chers sauf "Chocolat"
var filtered = products.Where(
    p => p.Price > 100 && p.Name != "Chocolat"
);

Filtrer sur une chaîne (sous-chaîne, casse, Contains)


// Les produits dont le nom contient la lettre "l"
var lProducts = products.Where(p => p.Name.Contains("l"));

Attention : Contains est sensible à la casse ! Si tu veux ignorer la casse, tu peux faire :


var lProducts = products.Where(p => p.Name
    .ToLower().Contains("l")); // maintenant "Lait" et "Chocolat" seront tous les deux pris

Filtrer sur plusieurs collections

Imaginons que t’as deux listes — produits et paiements. Tu peux filtrer les produits qui sont dans la liste des paiements — mais pour ça, c’est mieux d’utiliser Any et Join, on en parlera plus tard. Juste pour info : LINQ sait filtrer de façon bien plus balèze !

7. Petits tips utiles

Filtrage imbriqué et chaînes de méthodes

Tu peux enchaîner plusieurs étapes de filtrage en appelant Where plusieurs fois :


var filtered = products
    .Where(p => p.Price > 100)
    .Where(p => p.Name.StartsWith("Ch"));

Mais c’est mieux de regrouper les conditions dans un seul Where avec des opérateurs logiques — c’est plus efficace et plus lisible.

Comparateurs intégrés et fonctions custom

Parfois les opérateurs de base ne suffisent pas. Genre, tu veux filtrer des chaînes sans tenir compte de la casse et de la culture. Là, c’est pratique d’utiliser les méthodes de comparaison :


var frProducts = products.Where(
    p => p.Name.StartsWith("ch", StringComparison.OrdinalIgnoreCase)
);

8. Filtrage et input utilisateur

On va faire un petit filtrage interactif ! Par exemple, on demande à l’utilisateur le prix minimum, puis on affiche tous les produits qui vont bien.


Console.Write("Prix minimum du produit ? ");
var minPriceStr = Console.ReadLine();
if (double.TryParse(minPriceStr, out double minPrice))
{
    var filtered = products.Where(p => p.Price >= minPrice);
    foreach (var product in filtered)
    {
        Console.WriteLine(product);
    }
}
else
{
    Console.WriteLine("Erreur : ce n’est pas un nombre.");
}

Maintenant notre « mini-appli » ressemble déjà à une boutique !

9. Pièges et erreurs classiques avec Where

En prog comme dans la vie, y’a des pièges. Voilà ce qu’il faut surveiller.

Oublié d’appeler ToList() ou ToArray()

Le résultat de Where — c’est pas une liste ni un tableau ! C’est un objet IEnumerable<Product>. La plupart du temps ça roule dans une boucle foreach, mais si tu veux vraiment une collection (genre pour accéder par index), pense à appeler .ToList() ou .ToArray() :


var filteredList = products.Where(p => p.Price > 100).ToList();

Si tu zappes ça, tu peux avoir une erreur du genre "Collection was modified during enumeration" — surtout si tu modifies la collection de base pendant la boucle.

Modifier la collection de base

Comme le filtrage LINQ est différé, si tu supprimes des éléments de la liste de base pendant la boucle, tu peux avoir une exception. Surtout en multi-thread ou si la collection change pendant le filtrage.

Valeurs null et prédicats

Si la collection contient null et que tu accèdes à un champ dans le prédicat sans check, tu vas te prendre un NullReferenceException. Par exemple :


var filtered = products.Where(p => p.Name.StartsWith("A"));

Si un élément de products est null, ça va planter.

Conseil : mets toujours un check sur null si tu risques d’avoir ce genre d’éléments :


var filtered = products.Where(p => p != null && p.Name.StartsWith("A"));
2
Mission
C# SELF, niveau 31, leçon 2
Bloqué
Filtrer des objets selon plusieurs critères
Filtrer des objets selon plusieurs critères
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION