Maîtrise des opérateurs LINQ courants en C# pour requêtes efficaces

Comprendre LINQ

LINQ (Language Integrated Query) est une technologie intégrée dans les langages .NET comme C# et VB.NET, offrant une approche uniforme pour interroger des sources de données variées, y compris collections en mémoire, XML et bases de données relationnelles. Elle définit des opérateurs de requête standard qui fonctionnent sur les types implémentant IEnumerable ou IQueryable.

Avantages de LINQ

LINQ simplifie l'interaction entre objets et données en fournissant une interface de requête unique, éliminant le besoin de maîtriser plusieurs technologies d'accès aux données. Cela améliore la productivité et permet aux développeurs de se concentrer sur la logique métier.

Bibliothèque LINQ en C#

Dans l'espace de noms System.Linq, on trouve l'interface IEnumerable pour les collections en mémoire et IQueryable pour les requêtes différées. La classe Enumerable fournit des méthodes d'extension pour IEnumerable, tandis que Queryable les fournit pour IQueryable, avec des opérations telles que filtrage, tri et agrégation.

Types de LINQ

Les principales variantes incluent LINQ to Objects (collections en mémoire), LINQ to XML (documents XML) et LINQ to ADO.NET (bases de données). Les spécificités de chaque type peuvent être explorées dans des ressources dédiées.

Exemples de méthodes d'extension

Aggregate


List<int> chiffres = Enumerable.Range(1, 100).ToList();
int total = chiffres.Aggregate((accumulateur, valeur) => accumulateur + valeur);
Console.WriteLine($"Somme de 1 à 100 : {total}");

int comptePairs = chiffres.Aggregate(0, (compteur, element) => element % 2 == 0 ? compteur + 1 : compteur);
Console.WriteLine($"Nombre d'éléments pairs : {comptePairs}");
</int>

All


List<animal> animaux = new List<animal>
{
    new Animal { Id = "A01", Nom = "Chien", Age = 8 },
    new Animal { Id = "A02", Nom = "Chat", Age = 3 },
    new Animal { Id = "A03", Nom = "Oiseau", Age = 12 }
};

List<animal> selection = new List<animal>();
bool tousAdultes = animaux.All(a =>
{
    if (a.Age >= 5)
    {
        selection.Add(a);
        return true;
    }
    return false;
});

Console.WriteLine(tousAdultes ? "Tous les animaux sont adultes" : "Tous ne sont pas adultes");
Console.WriteLine($"Animaux adultes : {string.Join(", ", selection.Select(a => a.Nom))}");
</animal></animal></animal></animal>

Any


List<animal> animaux = new List<animal>
{
    new Animal { Id = "A01", Nom = "Chien", Age = 8 },
    new Animal { Id = "A02", Nom = "Chat", Age = 3 },
    new Animal { Id = "A03", Nom = "Oiseau", Age = 12 }
};

if (animaux != null && animaux.Any())
{
    List<animal> resultats = animaux.Where(a => a.Age >= 5).ToList();
    Console.WriteLine($"Animaux de plus de 5 ans : {string.Join(", ", resultats.Select(a => a.Nom))}");
}
else
{
    Console.WriteLine("Aucune donnée disponible.");
}
</animal></animal></animal>

Append


List<string> elements = new List<string> { "Bonjour", "le" };
elements = elements.Append("monde").ToList();
Console.WriteLine(string.Join(" ", elements));
</string></string>

AsEnumerable


CollectionPersonnalisee<string> collection = new CollectionPersonnalisee<string> { "texte1", "texte2", "texte3" };
var resultatPersonnalise = collection.MethodePersonnalisee(c => c.Contains('e'));
var resultatLinq = collection.AsEnumerable().Where(c => c.Contains('e'));
Console.WriteLine(string.Join(" ; ", resultatPersonnalise));
Console.WriteLine(string.Join(" | ", resultatLinq));
</string></string>

Average


IEnumerable<decimal> notes = new List<decimal> { 85, 90, 75, 92, 88 };
decimal moyenne = notes.Average();
Console.WriteLine($"Moyenne : {Math.Round(moyenne, 2)}");
</decimal></decimal>

Cast


ArrayList liste = new ArrayList { "100", "50", "75" };
var listeTriee = liste.Cast<int>().OrderByDescending(v => v).Select(v => v.ToString()).ToList();
Console.WriteLine(string.Join(" ", listeTriee));
</int>

Concat


List<string> groupe1 = new List<string> { "Alice", "Bob" };
List<string> groupe2 = new List<string> { "Charlie", "Diana" };
var tousMembres = groupe1.Concat(groupe2);
Console.WriteLine(string.Join(", ", tousMembres));
</string></string></string></string>

Contains


List<string> noms = new List<string> { "Alice", "Bob", "Charlie" };
if (noms.Contains("Bob"))
{
    Console.WriteLine("Bob est présent.");
}
</string></string>

Count


List<string> elements = new List<string> { "un", "deux", "trois" };
int nombre = elements.Count();
Console.WriteLine($"Nombre d'éléments : {nombre}");
</string></string>

DefaultIfEmpty


List<animal> animaux = new List<animal>
{
    new Animal { Id = "A01", Nom = "Chien", Age = 8 }
};

var resultat = animaux.Where(a => a.Age > 10).DefaultIfEmpty().ToList();
Console.WriteLine(resultat.First() == null ? "Aucun animal trouvé" : string.Join(", ", resultat.Select(a => a.Nom)));

var resultat2 = animaux.Where(a => a.Age > 10).DefaultIfEmpty(animaux.Last()).ToList();
Console.WriteLine(string.Join(", ", resultat2.Select(a => a.Nom)));
</animal></animal>

Distinct


List<string> villes = new List<string> { "Paris", "Lyon", "Paris", "Marseille" };
var villesUniques = villes.Distinct();
Console.WriteLine($"Villes uniques : {string.Join(", ", villesUniques)}");
</string></string>

ElementAt


List<string> fruits = new List<string> { "pomme", "banane", "cerise" };
Console.WriteLine($"Élément à l'index 2 : {fruits.ElementAt(2)}");
</string></string>

ElementAtOrDefault


List<string> fruits = new List<string> { "pomme", "banane", "cerise" };
string fruit = fruits.ElementAtOrDefault(5);
Console.WriteLine(fruit ?? "Index hors limites, retour par défaut : " + fruits.ElementAtOrDefault(2));
</string></string>

Empty


List<animal> animaux = new List<animal>();
var collectionVide = animaux.Any() ? animaux : Enumerable.Empty<animal>().ToList();
Console.WriteLine(collectionVide.Any() ? "Collection non vide" : "Collection vide");
</animal></animal></animal>

Except


List<int> liste1 = new List<int> { 1, 2, 3, 4, 5 };
List<int> liste2 = new List<int> { 4, 5, 6, 7, 8 };
var difference = liste1.Except(liste2);
Console.WriteLine($"Différence : {string.Join(", ", difference)}");
</int></int></int></int>

First et FirstOrDefault


int[] nombres = { 10, 20, 30, 40, 50 };
int premier = nombres.First();
Console.WriteLine($"Premier élément : {premier}");
int superieurCent = nombres.FirstOrDefault(n => n > 100);
Console.WriteLine(superieurCent == 0 ? "Aucun élément supérieur à 100" : $"Premier supérieur à 100 : {superieurCent}");

GroupBy


List<personne> personnes = new List<personne>
{
    new Personne { Nom = "Alice", Age = 25, Pays = "France", Genre = "F" },
    new Personne { Nom = "Bob", Age = 30, Pays = "Belgique", Genre = "M" },
    new Personne { Nom = "Charlie", Age = 28, Pays = "France", Genre = "M" },
    new Personne { Nom = "Diana", Age = 35, Pays = "Suisse", Genre = "F" }
};

var groupesParPays = personnes.GroupBy(p => p.Pays);
foreach (var groupe in groupesParPays)
{
    Console.WriteLine($"Pays : {groupe.Key}, Personnes : {string.Join(", ", groupe.Select(p => p.Nom))}");
}

var groupesParPaysEtGenre = personnes.GroupBy(p => new { p.Pays, p.Genre });
foreach (var groupe in groupesParPaysEtGenre)
{
    Console.WriteLine($"Pays : {groupe.Key.Pays}, Genre : {groupe.Key.Genre}, Noms : {string.Join(", ", groupe.Select(p => p.Nom))}");
}
</personne></personne>

GroupJoin


List<eleve> eleves = new List<eleve>
{
    new Eleve { Id = "E01", Nom = "Alice", LivreId = "L01" },
    new Eleve { Id = "E02", Nom = "Bob", LivreId = "L02" },
    new Eleve { Id = "E03", Nom = "Charlie", LivreId = "L03" }
};

List<livre> livres = new List<livre>
{
    new Livre { Id = "L01", Titre = "Le Petit Prince" },
    new Livre { Id = "L02", Titre = "Les Misérables" },
    new Livre { Id = "L03", Titre = "L'Étranger" }
};

var jointure = eleves.GroupJoin(livres, e => e.LivreId, l => l.Id, (e, livresAssocies) => new
{
    e.Nom,
    Livres = livresAssocies.Select(l => l.Titre).ToList()
});

foreach (var item in jointure)
{
    Console.WriteLine($"Élève : {item.Nom}, Livres : {string.Join(", ", item.Livres)}");
}
</livre></livre></eleve></eleve>

Intersect


List<int> ensemble1 = new List<int> { 1, 2, 3, 4, 5 };
List<int> ensemble2 = new List<int> { 4, 5, 6, 7, 8 };
var intersection = ensemble1.Intersect(ensemble2);
Console.WriteLine($"Intersection : {string.Join(", ", intersection)}");
</int></int></int></int>

Join


List<client> clients = new List<client>
{
    new Client { Id = "C01", Nom = "Alice" },
    new Client { Id = "C02", Nom = "Bob" }
};

List<commande> commandes = new List<commande>
{
    new Commande { ClientId = "C01", Montant = 100 },
    new Commande { ClientId = "C02", Montant = 200 }
};

var jointureInterne = clients.Join(commandes, c => c.Id, cmd => cmd.ClientId, (c, cmd) => new { c.Nom, cmd.Montant });
foreach (var item in jointureInterne)
{
    Console.WriteLine($"Client : {item.Nom}, Montant : {item.Montant}");
}
</commande></commande></client></client>

Last et LastOrDefault


int[] nombres = { 10, 20, 30, 40, 50 };
int dernier = nombres.Last();
Console.WriteLine($"Dernier élément : {dernier}");
int superieurMille = nombres.LastOrDefault(n => n > 1000);
Console.WriteLine(superieurMille == 0 ? "Aucun élément supérieur à 1000" : $"Dernier supérieur à 1000 : {superieurMille}");

Reverse


List<string> mots = new List<string> { "A", "B", "C" };
mots.Reverse();
Console.WriteLine($"Ordre inversé : {string.Join(", ", mots)}");
</string></string>

Repeat


IEnumerable<string> repetition = Enumerable.Repeat("Test", 5);
foreach (var element in repetition)
{
    Console.WriteLine(element);
}
</string>

Select


int[] ages = { 18, 16, 22, 17, 30 };
var adultes = ages.Where(a => a >= 18).Select(a => $"Âge adulte : {a}");
foreach (var item in adultes)
{
    Console.WriteLine(item);
}

SelectMany


List<bibliotheque> bibliotheques = new List<bibliotheque>
{
    new Bibliotheque { Id = "B01", Livres = new List<livre> { new Livre { Id = "L01", Titre = "Livre1" }, new Livre { Id = "L02", Titre = "Livre2" } } },
    new Bibliotheque { Id = "B02", Livres = new List<livre> { new Livre { Id = "L03", Titre = "Livre3" }, new Livre { Id = "L04", Titre = "Livre4" } } }
};

var tousLivres = bibliotheques.SelectMany(b => b.Livres).Where(l => l.Id == "L02" || l.Id == "L04");
foreach (var livre in tousLivres)
{
    Console.WriteLine($"Livre trouvé : {livre.Titre}");
}
</livre></livre></bibliotheque></bibliotheque>

SequenceEqual


List<int> sequence1 = new List<int> { 1, 2, 3 };
List<int> sequence2 = new List<int> { 1, 2, 3 };
List<int> sequence3 = new List<int> { 1, 2, 4 };
bool egales = sequence1.SequenceEqual(sequence2);
bool differentes = sequence1.SequenceEqual(sequence3);
Console.WriteLine($"Séquences égales : {egales}");
Console.WriteLine($"Séquences différentes : {differentes}");
</int></int></int></int></int></int>

Skip et Take


List<int> donnees = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var page = donnees.Skip(2).Take(3).ToList();
Console.WriteLine($"Éléments de la page : {string.Join(", ", page)}");
</int></int>

ThenBy et ThenByDescending


List<animal> animaux = new List<animal>
{
    new Animal { Id = "A01", Nom = "Chien", Age = 8 },
    new Animal { Id = "A02", Nom = "Chat", Age = 3 },
    new Animal { Id = "A03", Nom = "Oiseau", Age = 12 }
};

var triSimple = animaux.OrderBy(a => a.Id).ToList();
Console.WriteLine($"Tri par Id : {string.Join(", ", triSimple.Select(a => a.Nom))}");

var triMultiple = animaux.OrderBy(a => a.Id).ThenByDescending(a => a.Age).ToList();
Console.WriteLine($"Tri par Id puis Age décroissant : {string.Join(", ", triMultiple.Select(a => a.Nom))}");
</animal></animal>

Union


List<string> liste1 = new List<string> { "A", "B", "C" };
List<string> liste2 = new List<string> { "B", "C", "D" };
var union = liste1.Union(liste2);
Console.WriteLine($"Union : {string.Join(", ", union)}");
</string></string></string></string>

ToDictionary


List<personne> personnes = new List<personne>
{
    new Personne { Nom = "Alice", Age = 25 },
    new Personne { Nom = "Bob", Age = 30 }
};

Dictionary<string int=""> dictionnaire = personnes.ToDictionary(p => p.Nom, p => p.Age);
foreach (var paire in dictionnaire)
{
    Console.WriteLine($"Nom : {paire.Key}, Âge : {paire.Value}");
}
</string></personne></personne>

Sum, Min, Max, Average


List<decimal> valeurs = new List<decimal> { 10, 20, 30, 40, 50 };
decimal somme = valeurs.Sum();
decimal minimum = valeurs.Min();
decimal maximum = valeurs.Max();
decimal moyenne = valeurs.Average();
Console.WriteLine($"Somme : {somme}, Min : {minimum}, Max : {maximum}, Moyenne : {Math.Round(moyenne, 2)}");
</decimal></decimal>

ToLookup


List<animal> animaux = new List<animal>
{
    new Animal { Id = "A01", Nom = "Chien", Age = 8 },
    new Animal { Id = "A01", Nom = "Chien", Age = 8 },
    new Animal { Id = "A02", Nom = "Chat", Age = 3 }
};

var lookup = animaux.ToLookup(a => a.Id);
foreach (var groupe in lookup)
{
    Console.WriteLine($"Clé : {groupe.Key}, Éléments : {string.Join(", ", groupe.Select(a => a.Nom))}");
}
</animal></animal>

Zip


List<string> noms = new List<string> { "Alice", "Bob", "Charlie" };
List<int> ages = new List<int> { 25, 30, 28 };
var combines = noms.Zip(ages, (nom, age) => $"{nom} a {age} ans");
foreach (var element in combines)
{
    Console.WriteLine(element);
}
</int></int></string></string>

Classes de modèle utilisées


class Animal
{
    public string Id { get; set; }
    public string Nom { get; set; }
    public int Age { get; set; }
}

class Personne
{
    public string Nom { get; set; }
    public int Age { get; set; }
    public string Pays { get; set; }
    public string Genre { get; set; }
}

class Eleve
{
    public string Id { get; set; }
    public string Nom { get; set; }
    public string LivreId { get; set; }
}

class Livre
{
    public string Id { get; set; }
    public string Titre { get; set; }
}

class Bibliotheque
{
    public string Id { get; set; }
    public List<livre> Livres { get; set; }
}

class CollectionPersonnalisee<t> : List<t>
{
    public IEnumerable<t> MethodePersonnalisee(Func<t bool=""> predicate)
    {
        return Enumerable.Where(this, predicate);
    }
}
</t></t></t></t></livre>

Étiquettes: LINQ C# .NET extension methods query language

Publié le 22 juin à 17h03