Introduction à LINQ To Objects


Aujourd'hui nous allons découvrir les possibilités offertes par le framework Microsoft : LINQ.

LINQ permet de manipuler des données en base, des objets collections et des fichiers XML.
Nous allons consacrer ce premier article à LINQ To Objects à travers un exemple simple.
LINQ utilise les concepts introduits par le nouveau framework 3.0 :

Avant de poursuivre cet article, je vous conseille d'aller jeter un oeil sur ces concepts ici.

Dans notre projet VS 2008, pour nos tests, nous allons créer une application console.
Dans les options, choisissons le compilateur .NET 3.5.


Le projet contient alors par défaut les références aux librairies et l'import du namespace LINQ System.Linq


Nous allons ajouter à ce projet une classe Film :

    class Film
    {
        public string Nom { get; set; }
        public List<string> Categories { get; set; }
        public int AnneeProduction { get; set; }
    }

Par défaut, le projet contient un fichier Program.cs.
Celui-ci sera notre classe de test dans laquelle nous déclarons et définissons une liste de films :

List<Film> listFilms = new List<Film>{
    new Film { Nom = "Là-haut",
               Categories = new List<string>{"Animation"},
               AnneeProduction = 2009 },
    new Film { Nom = "Inglourious Basterds",
               Categories = new List<string>{"Guerre"},
               AnneeProduction = 2009 },
    new Film { Nom = "Shrek",
               Categories = new List<string>{"Animation"},
               AnneeProduction = 2001 },
    new Film { Nom = "Edward aux mains d'argent",
               Categories = new List<string>{"Fantastique", "Romance", "Comédie"},
               AnneeProduction = 1991 },
    new Film { Nom = "La Liste de Schindler",
               Categories = new List<string>{"Guerre", "Histoire", "Drame"},
               AnneeProduction = 1994 },
    new Film { Nom = "Forrest Gump",
               Categories = new List<string>{"Comédie", "Drame", "Romance"},
               AnneeProduction = 1994 },
    new Film { Nom = "L'âge des glaces 2",
               Categories = new List<string>{"Animation"},
               AnneeProduction = 2006 },
    new Film { Nom = "Gladiator",
               Categories = new List<string>{"Péplum", "Drame", "Action"},
               AnneeProduction = 2000 },
    new Film { Nom = "Princesse Mononoke",
               Categories = new List<string>{"Drame", "Fantastique", "Animation"},
               AnneeProduction = 2000 },
    new Film { Nom = "Pulp Fiction",
               Categories = new List<string>{"Policier"},
               AnneeProduction = 1994 },
    new Film { Nom = "Public Enemies",
               Categories = new List<string>{"Policier", "Drame"},
               AnneeProduction = 2009 },
    new Film { Nom = "Indiana Jones et le Temple maudit",
               Categories = new List<string>{"Aventure"},
               AnneeProduction = 1984 }
};

Question :

Comment feriez vous pour récupérer les films produits avant 2000 ?

Une solution possible est de faire :

List<Film> listFilmFiltre = new List<Film>();
foreach (Film f in listFilms)
{
    if (f.AnneeProduction < 2000)
        listFilmFiltre.Add(f);
}
// Afficher le contenu de listFilmFiltre

Cette approche programmatique : boucle foreach, vérification de condition, test en if ... fonctionne parfaitement.

On ne peut rien reprocher à cette série d'instructions, mais pour obtenir le même résultat, LINQ To Objects nous permet de faire beaucoup plus simple à l'aide des expressions query :

var listFilmFiltreLinq = from f in listFilms
                         where f.AnneeProduction < 2000
                         select f;
// Afficher le contenu de listFilmFiltreLinq

LINQ Propose de nombreuses méthodes d'extension appartenant à la classe System.Linq.Enumerable.
Ce sont, entre autres, les opérateurs Where, Select ..
Ces opérateurs s'appliquent exclusivement sur des objets de collections, précisément les objets implémentant l'interface IEnumerable<T>.

Une autre manière de faire en utilisant l'operateur Where de LINQ combiné aux expressions lambda :

/*** utilisation de l'opérateur Where ***/
   var listFilmFiltreLinq2 = listFilms.Where(f => f.AnneeProduction < 2000);
   // Puis afficher le contenu de la liste obtenue ...

Le résultat de l'opérateur Where sur la liste de films renvoie un objet IEnumerable<Film> contenant les films vérifiant le critère de filtre appliqué sur l'année par l'opérateur.


Par ailleurs, on peut se contenter d'obtenir la liste des noms de films à l'aide de l'opérateur Select de LINQ. Cet opérateur permet d'effectuer une projection i.e une sélection de propriétés caractéristiques d'un objet Film (ce qui correspond à une sélection de colonnes sur une table dans le domaine Relationnel) :

/*** utilisation des opérateurs Where, Select ***/
   var listFilmFiltreLinq3 =
       listFilms.Where(f => f.AnneeProduction < 2000).Select(f=>f.Nom);
   // Puis afficher le contenu de la liste obtenue :
   foreach (string sNomFilm in listFilmFiltreLinq3)
       Console.WriteLine(sNomFilm);

Le résultat obtenu est un objet IEnumerable<string> contenant le noms des films vérifiant le critère de filtre. La particularité de LINQ To Objects est de renvoyer des collections génériques.



Maintenant que nous connaissons un peu mieux LINQ To Objects, essayons de faire un peu plus complexe : récupérer la liste de tous les films appartenant à la catégorie "Animation" produits après l'année 2000.

/*** Les films d'animation produits après 2000 ***/
   var listFilmAnimation =
       listFilms.Where(f => f.Categories.Contains("Animation")
                               && f.AnneeProduction > 2000);
   // Puis afficher le contenu de la liste obtenue :
   Film.afficherlisteFilms(listFilmAnimation);

 

Enfin, on organise la liste obtenue des films du plus récent au plus ancien, en utilisant l'opérateur OrderByDescending :

/*** Les films d'animation ordonnés du plus récent au plus ancien ***/
   var listFilmAnimationOrder =
       listFilmAnimation.OrderByDescending(f => f.AnneeProduction);

   // Puis afficher le contenu de la liste obtenue :
   Film.afficherlisteFilms(listFilmAnimationOrder);


J'espère que cette petite présentation vous donnera envie de continuer d'approfondir les possibilités de LINQ To Objects. Possibilités offertes par bon nombre de méthodes d'extension/d'opérateurs de la classe Enumerable.

Télécharger le projet

0 commentaires:

Enregistrer un commentaire