.Net 3.5 : LINQ to Objects / C# : les premiers pas

Ronald Vasseur

Le Framework .Net 3.5 a apporté quelques améliorations et évolutions dont une qui fait beaucoup parler d'elle dans le petit monde des développeurs .Net, il s'agit de LINQ (pour Language Integrated Query). Il s'agit en fait d'un ensemble de classes et de méthodes permettant de requêter des objets et des sources de données au sens large un peu à la manière de SQL directement dans le code .Net.

- Titre : .Net 3.5 : LINQ to Objects / C# : les premiers pas

- Auteur : Ronald Vasseur

- Parution : 1 novembre 2008

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2008 Ronald Vasseur. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. LINQ, qu'est-ce que c'est ?

- 2. LINQ to objects par le code

- 2-1. Requêter une collection

- 2-2. Calcul d'agrégat

- 2-3. Regroupement

- 2-4. Classement

- 3. Conclusion

- Ressources

- Liens vers le MSDN

- Liens vers Developpez.com

1 - LINQ, qu'est-ce que c'est ?

Le Framework .Net 3.5 a apporté quelques améliorations et évolutions dont une qui fait beaucoup parler d'elle dans le petit monde des développeurs .Net, il s'agit de LINQ (pour Language Integrated Query). Il s'agit en fait d'un ensemble de classes et de méthodes permettant de requêter des objets et des sources de données au sens large un peu à la manière de SQL directement dans le code .Net. Vous allez me dire il y "a déjà SQL pour cela", oui mais non, en effet LINQ permet de requêter des bases de données, mais également des objets, des collections, des fichiers XML, des datasets...

En effet jusqu'à maintenant quand il fallait faire des recherches dans des listes génériques en fonction de critères précis cela s'avérait souvent fastidieux. Imaginez une collection contenant 10000 objets développeurs, s'il faut retourner les développeurs (les objets développeur) dont le nom est complété, dont l'âge est au moins 25 ans, dont le salaire est inférieur à 30000 euros, et tout cela trié par ordre croissant sur le nom de la société à laquelle ils appartiennent. Cela est certes faisable mais faire cela simplement et en quelques lignes de code n'était à ce jour par possible en .Net, avec LINQ rien de plus simple !

Avant de rentrer un peu plus dans le code et "le comment" voyons un peu plus en détail ce qu'est LINQ.

Il existe actuellement 5 versions de LINQ fournies par défaut dans le Framework .Net 3.5 qui permettent de requêter des sources de données qui peuvent être les suivantes :

- Base SQL

- Objets

- Entités

- XML

- Dataset

LINQ offre un modèle ouvert et il est par exemple possible d'implémenter ses propres opérateurs. LINQ s'appui sur un certain nombre de nouveautés apportées par C# 3.0 et VB.Net 9.0 pour pouvoir s'intégrer au mieux dans ces langages.

2 - LINQ to objects par le code

2-1 - Requêter une collection

Pour bien comprendre le fonctionnement de LINQ voyons ce que cela donne dans le code quand l'on souhaite requêter une collection. Nous allons commencer avec un exemple simple en créant une liste générique de chaînes de caractères, puis en la requêtant à l'aide de LINQ.

List<Developer> developers = new List<Developer>
{
new Developer{ Firstname = "Pierre", Lastname = "Martin", Age= 27, Company="Microsoft", Payroll=25000 },
new Developer{ Firstname = "Jean", Lastname = "Dupond", Age= 47, Company="Sun", Payroll=75000 },
new Developer{ Firstname = "Paul", Lastname = "Leroi", Age= 21, Company="Google", Payroll=20000 },
new Developer{ Firstname = "Victor", Lastname = "Duchemin", Age= 32, Company="IBM", Payroll=35000 },
new Developer{ Firstname = "Louis", Lastname = "Dupont", Age= 28, Company="Intel", Payroll=55000 },
new Developer{ Firstname = "Henry", Lastname = "Duclos", Age= 29, Company="Dell", Payroll=18000 },
new Developer{ Firstname = "Michel", Lastname = null, Age= 29, Company="Bull", Payroll=18000 },
new Developer{ Firstname = "Stephane", Lastname = "", Age= 29, Company="Amiga", Payroll=18000 },
new Developer{ Firstname = "Marcel", Lastname = "Merlin", Age= 29, Company="AMD", Payroll=45000 },
};

var requestedDevelopers = from dev in developers
where dev.Age > 25 && dev.Payroll < 30000 && dev.Lastname != null && dev.Lastname != string.Empty
orderby dev.Company ascending
select dev;

Comme on le voit grâce aux instructions de LINQ, très proches de celles du langage SQL, il est possible de filtrer les données selon des critères et des paramètres précis, exactement comme lorsque l'on requête une base de données, mais tout cela directement dans notre code .Net. Il sera donc par exemple très facile de débugger notre code. Comme SQL, LINQ nous offre de nombreux opérateurs, voici la liste des plus communs :

- Select, SelectMany

- Where

- Join

- Reverse, OrderBy

- Sum, Max, Min, Average, Count

Pour information LINQ offre plusieurs dizaines de mots clés et éléments !

Comme nous venons de le voir avec ce premier exemple, l'ordre des opérateurs est quasiment inverse par rapport à SQL, par exemple l'on commence par From et l'on termine par Select ! Ce n'est pas pour embêter le développeur mais entre autre pour pouvoir bénéficier de l'IntelliSense lors de l'écriture d'une requête.

Passons maintenant à la découverte de fonctionnalités de LINQ que vous risquez d'utiliser fréquemment.

2-2 - Calcul d'agrégat

Un calcul d'agrégat permet de calculer une somme, une moyenne, un maximum... Prenons une liste de commandes et calculons le montant des commandes de plus de 100 euros :

Calcul d'une somme

List<Order> orders = new List<Order>
{
new Order{ Amount = 8978M, CustomerName ="Dupond", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 78M, CustomerName ="Martin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 157M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
};

var ordersSum = (from ord in orders
where ord.Amount > 100
select ord.Amount).Sum();

2-3 - Regroupement

Nous allons voir ici comment regrouper les résultats d'une requête en fonction d'une clé déterminée, comme par exemple regrouper les commandes par clients. Voici comment procéder :

List<Order> orders = new List<Order>
{
new Order{ Amount = 15M, CustomerName ="Martin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 3M, CustomerName ="Martin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 65M, CustomerName ="Martin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 11M, CustomerName ="Dupond", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 43M, CustomerName ="Dupond", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 8M, CustomerName ="Dupond", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 157M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 7M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 76M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 9M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
};

var ordersGroupedByName = from ord in orders
group ord by ord.CustomerName;

2-4 - Classement

Avec l'opérateur OrderBy il est possible de classer les résultats d'une requête dans l'ordre croissant ou décroissant sur un champ donné.

List<Order> orders = new List<Order>
{
new Order{ Amount = 78M, CustomerName ="Martin", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 8978M, CustomerName ="Dupond", Date = DateTime.Parse("01/01/2008") },
new Order{ Amount = 157M, CustomerName ="Merlin", Date = DateTime.Parse("01/01/2008") },
};

var ordersByName = from ord in orders
orderby ord.CustomerName ascending
select ord.CustomerName;

3 - Conclusion

J'espère au travers de cet article vous avoir montré dans les grandes lignes les possibilités offertes par LINQ to object. Avec LINQ il est désormais possible de requêter des listes d'objets très facilement de manière aussi poussée que ce que l'on pourrait faire avec SQL sur une base de données. Il est de plus important de garder à l'esprit que LINQ ne se limite pas aux objets seulement mais à une grande variété de sources de données. A bientôt pour d'autres articles consacrés à LINQ.

Ressources

Liens vers le MSDN

Un excellent article de Don Box, Anders Hejlsberg sur MSDN
LINQ sur Wikipedia

Liens vers Developpez.com

Mes articles
Mon blog
Les articles des autres rédacteurs
La rubrique .Net de Developpez.com