Frédéric Mélantois
Comprendre les bases de Linq to objects
La meilleure façon de comprendre le fonctionnement de Linq est sans doute de réaliser soi-même un petit développement similaire en C# 2.0 et de le faire évoluer sous C# 3.0 en intégrant chaque nouveauté du langage.
Par Frédéric Mélantois publié le 21/10/2007 à 22:53, lu 6925 fois, 6 pages
 5 | De l'usage de Linq
Jusqu'à présent, nous n'avons pas fait usage du mode de requêtes Linq. Pour cela, via la directive « using », nous allons donc inclure l'espace de nom suivant : « System.Linq ». Je vous propose de découvrir les différentes façons de formuler la demande effectuée au chapitre précédent :

IEnumerable<IEnumerable<float>> t = ComplementEnumerable.Select<EleveENT, IEnumerable<float>>(l,

    delegate(EleveENT c)

    {

        return ComplementEnumerable.Select<NoteENT, float>(ComplementEnumerable.Where<NoteENT>(c.Notes,

            delegate(NoteENT n)

            { return n.Date >= new DateTime(2007,4,1); }

            ), delegate(NoteENT n)

            { return n.Note; }

        );

    });

 

var r = ComplementEnumerable.Select(l, c =>

    ComplementEnumerable.Select(ComplementEnumerable.Where(c.Notes, n =>

    n.Date >= new DateTime(2007,4,1)), f => f.Note)

);

 

var h = l.Select(c => c.Notes.Where(n => n.Date >= new DateTime(2007,4,1)).Select(f => f.Note));

 

var p = from w in l select w.Notes.Where(n => n.Date >= new DateTime(2007,4,1)).Select(f => f.Note);

 

var z = (from k in l select (from q in k.Notes where q.Date >= new DateTime(2007,4,1) select q.Note));

On peut se poser plusieurs questions. La première est : Les résultats obtenus pour chacune des formulations sont-ils identiques ? La réponse est évidemment affirmative. Vous pouvez le vérifier grâce à la console. La deuxième question est : Ces syntaxes sont-elles véritablement équivalentes pour le code généré ? L'analyse de l'IL via le désassembleur va nous permettre de répondre. En effet, pour les cinq syntaxes ci-dessus, le code IL est identique.
Mais il ne s'agit pas du seul constat que l'on peut faire. En effet, on aurait pu s'attendre à voir des appels aux méthodes de « System.Linq.Enumerable » où l'on retrouve les mêmes signatures que nos méthodes de notre « ComplementEnumerable ». Mais le compilateur C# en analysant les requêtes « Linq » considère les méthodes de « ComplementEnumerable » comme des « surcharges » des méthodes de System.Linq.Enumerable. En conséquence, ce choix explique que l'IL soit identique pour les cinq syntaxes ci-dessus. Autre conséquence, il est donc possible de « modifier » les méthodes de « System.Linq.Enumerable » qui ne nous plairaient pas. A la vue de ces résultats, on aimerait comparer L'IL généré à partir de la base « ComplementEnumerable » et l'IL généré à partir de « System.Linq » en ayant désactivé notre classe « ComplementEnumerable ». Sachez que l'IL est complètement équivalent si on ne porte pas la comparaison aux méthodes « Select », « Where » qui proviennent soit de notre classe « ComplementEnumerable » soit de la classe « System.Linq.Enumerable » de l'assembly « System.Core » fourni par le Framework 3.5.
Nous sommes donc parvenus à montrer les bases du fonctionnement de Linq (to Objects) à travers notre exemple construit initialement en C# 2.0. D'ailleurs, si vous pensez bien avoir compris, vous pouvez vous livrer au jeu suivant : Quelle requête est la plus performante ?

var r1 = l.Average(c => c.Notes.Average(n=> n.Note));

 

var r2 = (from k in l select (from q in k.Notes select q.Note).Average()).Average();

 

var r3 = (from w in l from o in w.Notes select w.Notes.Average(x => x.Note)).Average();

 
» Démarrer une discussion
 
Discussion démarée par Matthieu Mezil le 22/10/2007 à 11:37, 1 commentaire(s).