Etude exploratoire de Linq - CoDE - de l'Université libre de Bruxelles
Etude exploratoire de Linq - CoDE - de l'Université libre de Bruxelles
Etude exploratoire de Linq - CoDE - de l'Université libre de Bruxelles
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
2.2.2 Expressions lambda<br />
Cette sous-section rassemble également <strong>de</strong>s informations provenant <strong>de</strong> [1] et <strong>de</strong> [6]. Le type<br />
<strong>de</strong>legate introduit avec la version 2 du framework .NET représente un moyen <strong>de</strong> faire pointer du<br />
co<strong>de</strong> vers une fonction définie ailleurs. L’expression lambda simplifie cette pratique et permet plus<br />
<strong>de</strong> souplesse à l’utilisation. Ceci s’avère particulièrement utile pour l’écriture <strong>de</strong> métho<strong>de</strong>s<br />
anonymes, comme le montre l’exemple suivant (trouvé sur [6]) :<br />
//metho<strong>de</strong> anonyme recuperant les entiers positifs, ecrite avec la<br />
//syntaxe 2.0<br />
List list = new List(new int[] { -1, 2, -5, 45, 5 });<br />
List positiveNumbers = list.FindAll(<strong>de</strong>legate(int i) { return i ><br />
0; });<br />
//meme co<strong>de</strong> ecrit avec une expression lambda<br />
List list = new List(new int[] { -1, 2, -5, 45, 5 });<br />
var positiveNumbers = list.FindAll((int i) => i > 0);<br />
La syntaxe d’une expression lambda est toute simple. Elle se compose d’une liste <strong>de</strong> paramètres (un<br />
seul, dans l’exemple ci-<strong>de</strong>ssus, l’entier i), du symbole « => » intuitivement traduit par « tel que » et<br />
d’une expression qui constitue en fait la valeur retournée par l’expression lambda. Cette formulation<br />
est bien plus lisible et se prononce « tous les entiers i tels que la valeur <strong>de</strong> i est strictement<br />
supérieure à 0 ». Un autre avantage est que la valeur retournée par l’expression lambda est typée<br />
implicitement, comme l’indique le mot-clé var dans l’exemple précé<strong>de</strong>nt.<br />
En plus d’une simplicité d’écriture pour les métho<strong>de</strong>s anonymes, les expressions lambda permettent<br />
<strong>de</strong> traiter <strong>de</strong>s expressions proches <strong>de</strong>s clauses Sql. Ainsi une clause Where dans une requête Sql peut<br />
se voir comme une condition <strong>de</strong> filtrage du résultat. Pour exprimer ceci en termes d’expressions<br />
lambda, nous appelons notre condition <strong>de</strong> filtrage définie par une expression lambda sur le résultat,<br />
<strong>de</strong> cette manière résultat.Filtrage(conditions). Le résultat <strong>de</strong> ce filtrage peut être lui-même soumis à<br />
d’autres opérations <strong>de</strong> ce type, présentant l’avantage <strong>de</strong> pouvoir lire les opérations séquentiellement<br />
<strong>de</strong> gauche à droite : résultat.Filtre1( condition1.1, condition1.2).Filtre2( condition2.1, … condition2.n)<br />
et ainsi <strong>de</strong> suite. C’est ainsi que <strong>Linq</strong> en fait usage, pour passer à chaque opérateur <strong>de</strong> clause le<br />
résultat créé par l’appel <strong>de</strong>s clauses précé<strong>de</strong>ntes : EnsembleFrom.Where(clause where).Select(clause<br />
select).Or<strong>de</strong>rBy(critère <strong>de</strong> tri). Nous ne parlons ici que <strong>de</strong>s clauses au sens relationnel du terme, le Sql<br />
étant <strong>de</strong>venu en quelque sorte le standard pour interroger <strong>de</strong>s données, nous nous contentons<br />
d’utiliser ici l’analogie. Nous verrons plus loin que <strong>Linq</strong> a adopté une syntaxe qui en est très proche.<br />
2.2.3 Expressions arborescentes<br />
Agir sur une source <strong>de</strong> données implique <strong>de</strong> pouvoir naviguer, disons, parmi les nœuds <strong>de</strong> sa<br />
structure. La notion <strong>de</strong> relation entre <strong>de</strong>s données stockées caractérise ceci au niveau conceptuel,<br />
mais en pratique, qu’en est-il ? Pour <strong>de</strong>s collections d’objets en mémoire, <strong>de</strong>s itérateurs ou <strong>de</strong>s<br />
métho<strong>de</strong>s <strong>de</strong> saut à un autre élément sont généralement fournis par la collection elle-même. Pour<br />
une structure relationnelle, les relations sont réalisées par <strong>de</strong>s jointures entre plusieurs tables. Aucun<br />
mécanisme orienté objet ne permet d’appeler une fonction qui sautera directement vers l’élément<br />
désiré. Le problème est le même lorsqu’on manipule <strong>de</strong>s données en Xml bien que, dans ce cas, la<br />
syntaxe <strong>de</strong>s requêtes soit plus proche du paradigme objet. Pour résoudre ce problème, les<br />
expressions arborescentes (expression tree, en Anglais) ont vu le jour. L’intérêt n’est pas tant <strong>de</strong><br />
manipuler en soi la source <strong>de</strong> données mais plutôt <strong>de</strong> pouvoir naviguer dans un résultat et surtout<br />
dans une requête. Comprendre la notion <strong>de</strong> jointure est indispensable pour écrire une requête qui y