Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Class Helper, LINQ et fichiers CSV

C# 3.0 a apporté des nouveautés syntaxiques qui ne se bornent pas à être seulement des petits suppléments qu'on peut ignorer, au contraire il s'agit de modifications de premier plan qui impactent en profondeur la façon d'écrire du code si on sait tirer partie de ces nouveautés. J'en ai souvent parlé, au travers de billets de ce blog ou d'articles comme celui décrivant justement les nouveautés syntaxiques de C#3.0. Je ne vais donc pas faire de redites, je suppose que vous connaissez maintenant tous ces ajouts au langage. Ce que je veux vous montrer c'est qu'en utilisant correctement C# 3.0 on peut écrire un code incroyable concis et clair pour résoudre les problèmes qui se posent au quotidien au développeur.

Le problème à résoudre

Vous recevez un fichier CSV, disons le résultat d'une exportation depuis un soft XY des ventes à l'export de votre société. Vous devez rapidement ajouter la possibilité d'importer ces données dans l'une de vos applications mais après les avoir interprétées, triées, voire filtrées.

La méthode la plus simple

Rappel : un fichier CSV est formé de lignes comportant plusieurs champs séparés par des virgules. Les champs peuvent être délimités par des double quotes.

A partir de cette description voyons comment avec une requête LINQ nous pouvons lire les données, les filtrer, les trier et les mettre en forme. Le but ici sera de générer en sortie une chaîne par enregistrement, chaîne contenant des champs "paddés" par des espaces pour créer un colonnage fixe. On tiendra compte des lignes débutant par le symbole dièse qui sont considérées comme des commentaires.

   1:  string[] lines = File.ReadAllLines("Export Sales Info-demo.csv");
   2:  var t1 = lines
   3:      .Where(l => !l.StartsWith("#"))
   4:      .Select(l => l.Split(','))
   5:      .OrderBy(items=>items[0])
   6:      .Select(items => String.Format("{0}{1}{2}",
   7:          items[1].PadRight(15),
   8:          items[2].PadRight(30),
   9:          items[3].PadRight(10)));
  10:  var t2 = t1
  11:      .Select(l => l.ToUpper());
  12:  foreach (var t in t2.Take(5))
  13:      Console.WriteLine(t);

La sortie (avec le fichier exemple fourni) sera :

SAN JOSE       CITY CENTER LODGE             CA
SAN FRANCISCO  KWIK-E-MART                   CA
SEATTLE        LITTLE CORNER SWEETS          WA
SEATTLE        LITTLE CORNER SWEETS          WA
IRVINE         PENNY TREE FOODS CORPORATION  CA
 

Cette méthode, très simple, ne réclame rien d'autre que le code ci-dessus. La solution est applicable à tout moment et s'adapte facilement à toute sorte de fichiers sources. Elle possède malgré tout quelques faiblesses. Par exemple les champs contenant des doubles quotes ou les champs mal formés risquent de faire échouer la séquence. Dans certains cas cela sera inacceptable, dans d'autres on pourra parfaitement protéger la séquence dans un bloc try/catch et rejeter les fichiers mal formés. Une fois encore il ne s'agit pas ici de montrer un code parfaitement adapté à un problème précis, mais bien de montrer l'esprit, la façon d'utiliser C# 3.0 pour résoudre des problèmes courants. 

Expliquons un peu ce code :

la ligne 1 charge la totalité du fichier CSV dans un tableau de strings. La méthode peut sembler "brutale" mais en réalité elle est souvent très acceptable car de tels fichiers dépassent rarement les quelques dizaines ou centaines de Ko et la RAM de nos machines modernes n'impose en rien une lecture bufferisée, tout peut tenir d'un bloc en mémoire sans le moindre souci. Cela nous arrange ici il faut l'avouer mais l'utilisation d'un flux bufferisé resterait parfaitement possible.

Nous disposons maintenant d'un tableau de chaînes, chacune étant formatée en CSV. La première requête LINQ (variable "t1" en ligne 2) fait l'essentiel du travail :

  • gestion des commentaires (ligne 3)
  • décomposition des champs (ligne 4)
  • tri sur l'un des champs (ligne 5)
  • génération d'une sortie formatée (lignes 6 à 9)

Ce qui est merveilleux ici c'est que nous avons en quelques lignes un concentré de ce qu'est une application informatique : acquisition de données, traitement de ces données, production de sorties exploitables par un être humain ou une autre application. En si peu de lignes nous avons réalisé ce qui aurait nécessité une application entière avec les langages de la génération précédente comme C++ ou Delphi. C'est bien ce bond en avant que représente C# 3.0 qui est ici le vrai sujet du billet.

Une méthode plus complète

La séquence que nous avons vu plus haut répond au problème posé. Elle possède quelques lacunes. Celles liées à sa trop grande simplicité (certains cas du parsing CSV ne sont pas correctement pris en compte) et celles liées à sa forme : c'est un bout de code qu'il faudra copier/coller pour le réutiliser et qui viendra "polluer" nos requêtes LINQ les rendant plus difficiles à lire.

Si ces lacunes sont acceptables dans certains cas (règlement ponctuel d'un problème ponctuel) dans d'autres cas on préfèrera une approche plus facilement réutilisable. Notamment si nous sommes amenés à traiter plus ou moins souvent des fichiers CSV nous avons intérêt à encapsuler le plus possible le parsing et à le rendre plus facilement reexploitable.

L'une des voies serait de créer une classe totalement dédiée à cette tâche. C'est une solution envisageable mais elle est assez lourde et amène son lots de difficultés.

Nous allons choisir ici une autre approche, celle de la création d'un class helper. C'est à dire que nous souhaitons non pas créer une classe qui traite un fichier CSV comme un tout, mais nous voulons pouvoir parser n'importe quelle chaîne de caractères formatée en CSV. L'approche est très différente. Dans le premier cas il nous faudra complexifier de plus en plus notre classe, voire créer une hiérarchie de classes pour traiter les fichiers CSV mais aussi les flux mémoire CSV, et puis encore les services Web retournant du CSV, etc, etc.

Dans le second cas nous allons plutôt ajouter la capacité à la classe string de parser une chaîne donnée. La source de la chaîne ne nous importe pas. Il pourra s'agir d'un élément d'un tableau de chaîne comme dans le premier exemple autant que d'une chaîne lue depuis un flux mémoire, une section data d'un fichier XML, etc. D'un certain sens nous acceptons d'être moins "complet" que l'option "classe dédiée CSV", mais nous gagnons en agilité et en "réutilisabilité" en faisant abstraction de la provenance de la chaîne à parser. Bien entendu nous pouvons nous offrir le luxe d'une telle approche car nous savons que nous pouvons nous reposer sur C# 3.0, ses class helpers et LINQ...

Le projet qui accompagne ce billet contient tout le code nécessaire et même un fichier CSV d'exemple, nous n'entrerons pas dans les détails de l'implémentation du class helper lui-même qui étend la classe string, parser du CSV n'est qu'un prétexte sans plus d'intérêt dans ce billet. Le code utilisé pour l'exemple provient d'ailleurs d'un billet de  Eric White dont vous pouvez visiter le blog si vous lisez l'anglais.

la façon d'écrire un class helper est décrite dans mon article sur C# 3.0, regardons juste sa déclaration :

public static string[] CsvSplit(this String source)

Cette méthode est déclarée au sein d'une classe statique de type "boîte à outils" pouvant centraliser d'autres méthodes utilitaires. La déclaration nous montre que le class helper s'applique à la classe String uniquement (this String source) et qu'elle retourne un tableau de chaîne (string[]).

Une fois le class helper défini (code complet dans le projet accompagnant l'article) il nous est possible d'écrire des requêtes LINQ du même type que celle du premier exemple. Mais cette fois-ci le parsing CSV est réalisé par le class helper ce qui permet à la fois de le rendre plus sophistiqué et surtout de ne plus avoir à le copier/coller dans les requêtes LINQ...

Voici un exemple d'utilisation du class helper sur le même fichier CSV. Ici nous parsons la source, nous la trions, nous éliminons les lignes de commentaire mais aussi nous créons en réponse une classe anonyme contenant le nom du contact, sa ville et le nom de sa société. Il est dès lors possible de traiter la liste d'objets résultat comme n'importe quelle liste : affichage, traitement, génération d'état, etc.

   1:  var data = File.ReadAllLines("Export Sales Info-demo.csv").Where(s=>!s.StartsWith("#"))
   2:      .Select(l =>
   3:  {
   4:  var split = l.CsvSplit();
   5:  return new
   6:             {
   7:                 Contact = split[0],
   8:                 City = split[1],
   9:                 Company = split[2]
  10:             };
  11:  }  ).OrderBy(x=>x.Contact);
  12:   
  13:  foreach (var d in data.Take(5))
  14:      Console.WriteLine(d);

Ce qui, avec le même fichier source, affichera à la console :

{ Contact = Allen James, City = San Jose, Company = City Center Lodge }
{ Contact = Bart H. Perryman, City = San Francisco, Company = Kwik-e-mart }
{ Contact = Beth Munin, City = Seattle, Company = Little Corner Sweets }
{ Contact = Beth Munin, City = Seattle, Company = Little Corner Sweets }
{ Contact = Bruce Calaway, City = Irvine, Company = Penny Tree Foods Corporation } 

Conclusion

La bonne utilisation de C# 3.0 permet de réduire significativement la taille du code donc de réduire dans les mêmes proportions les bugs et d'augmenter la productivité. Apprendre à utiliser cette nouvelle approche c'est gagner sur tous les plans...

 

Le projet exemple : LinqToCsv.zip (9,46 kb)

Donnez des couleurs à Blend et Design (intégration de Adobe Kuler).

Comme une coïncidence je parlais de Adobe dans mon dernier billet... Et si je n'en faisais pas forcément l'éloge pour la facette programmation de leurs outils, en revanche je reconnaissais bien volontier leur talent en ce qui concerne les outils de graphisme. En voici une illustration, et un moyen de récupérer ce savoir-faire dans les produits de design de la gamme Microsoft Expression !

Adobe a mis en ligne un site qui s'appelle Adobe Kuler, son utilité est de permettre facilement, et visuellement, de créer des nuanciers de couleurs. Les graphistes utilisent fréquemment les nuanciers car une fois ajoutés à un projet ils sont le garant du respect de la charte décidée pour celui-ci.

Bien entendu les outils tels que Expression Design ou Expression Blend savent gérés les nuanciers, chacun à sa façon. Design le gère de façon similaire à Adobe Illustrator, Blend le fait sous la forme de ressources de brosses. Mais qu'importe la technique exacte cela revient au même. Surtout, les contraintes qu'un graphiste doit prendre en compte restent les mêmes, qu'il travaille sous Illustrator ou Design ou même Blend : le respect de la charte est essentiel.

Je ne pourrais pas dire, faute de le connaître, si Jonas Follesoe est type bien ou sympa, en revanche je peux vous affirmer que c'est un bon développeur WPF qui aime Blend et Design ! Et il a créé un add-in pour ces deux produits qui permet de disposer d'une palette supplémentaire se connectant à Adobe Kuler pour aller y chercher des nuanciers !

Recherche des favoris, des plus populaires, etc, voire recherche sur un mot (tous les nuanciers "ocean" par exemple), tout cela est possible. On récupère les nuanciers par simple copie dans le logiciel (ou même par drag'n drop). C'est vraiment génial. D'autant qu'on peut aussi accéder au site Adobe Kuler pour modifier un nuancier ou en créer un totalement nouveau. Le site propose des modes intelligents comme la création de palettes à partir d'algorithmes de type couleurs complémentaires, nuancier monochromatique, etc.

Toutes les instructions pour télécharger le plugin Blend/Design ainsi que l'application WPF stand-alone sur son le blog de Jonas.

Le site Adobe Kuler vaut lui aussi une visite si vous ne connaissez pas.

Enfin, le projet de Jonas est sur CodePlex, dont open source, toujours bon pour repiquer les bonnes idées de développement et progresser dans son apprentissage !

Et comme c'est joli toutes ces couleurs, voici une petite capture écran du plugin en action sur mon Blend 2 SP1 :

 

Open XML SDK et PowerTools pour OOXML - Manipuler les documents OOXML

Le format Open XML utilisé par Microsoft pour sa suite Office est une grande avancée en ce sens que le stockage n'est plus propriétaire et que cela permet d'envisager de nombreux traitements automatiques des documents qu'il s'agisse de recherche documentaire, de modification ou même de création de nouveaux documents.

Le format en lui même est aujourd'hui normalisé ISO/IEC et même si on peut regretter la guerre des formats entre Open XML de Microsoft et OpenDocument, il va falloir apprendre à jongler avec ces deux normes ouvertes, aucune n'étant plus "sympathique" ou "meilleure", et chacune affichant ses petites différences. Quoi qu'il en soit, dans les faits la masse de documents produite par la suite Office dans le monde est tellement gigantesque qu'au final le développpeur aura forcément plus souvent affaire à de l'Open XML qu'à du OpenDocument.

Il faut donc saluer Microsoft d'avoir opté pour un nouveau format lisible, public et normalisé. Pour nous, informaticiens, c'est la seule chose qui compte. Laissons les querelles de format à ceux qui ont du temps à perdre...

Open XML SDK 

Même si OOXML est une norme claire, les documents la décrivant sont, comme toute norme, un peu imbuvables, avouons-le... Mais bien heureusement il existe un SDK gratuit "Open XML SDK" qui se compose d'aide et d'une librairie de classes .NET facilitant la manipulation des fichiers de type Word, Excel, PowerPoint...

Vous pouvez télécharger le OOXML SDK en cliquant sur le lien.

Une fois cet assemblage référencé, vos applications peuvent facilement traiter tout document Office.

A titre d'exemple vous trouverez un petit projet console qui permet de lister le contenu d'un fichier OOXML (Word, Excel, PowerPoint). J'ai supprimé du projet les fichiers de test, il vous suffira de modifier le code de la méthode Main pour y placer le chemin d'un fichier OOXML se trouvant sur votre machine (ou une copie si vous être méfiant ! ).

Voici un exemple de sortie sur un fichier Excel très simple :

URI                        Content Type
===                        ============
/xl/workbook.xml           application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
/xl/worksheets/sheet.xml   application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
 

Ce n'est qu'une sorte de "hello world", le SDK permettant de vraiment traiter les documents et de faire des choses bien plus sophistiquées, bien entendu !

PowerTools pour OOXML

Les PowerTools pour OOXML sont eux une autre couche s'utilisant d'ailleurs avec PowerShell dont je vous parlais dernièrement. C'est un projet open source sur CodePlex dont le but est d'autoriser le traitement de fichiers OOXML côté serveur. Par exemple produire directement un document Word ou Excel sur un serveur Web pour l'envoyer à l'utilisateur, faire des recherches dans une base documentaire, etc...

Lien : PowerTools OOXML sur CodePlex

On notera ce billet Julien Chable sur l'installation des PowerTools (en français, pour une fois...), ainsi qu'une vidéo de présentation (US) sur MSN Video

L'avantage de la combinaison des PowerTools OOXML au PowerShell et ses scripts est de former un ensemble permettant de traiter automatiquement des documents Offices en dehors de toute application. C'est donc une autre façon de traiter les documents Office que celle proposée par le SDK présenté plus haut.

Un exemple concret d'utilisation parmi des milliers d'autres : ajouter un filigrane avec le nom de la société ou une mention "ne pas diffuser" (ou autre) automatiquement à tous les documents d'un répertoire.  On peut même concevoir un service Windows surveillant un ou plusieurs répertoires et ajoutant systématiquement une mention, un logo, un filigrane, etc, à tout nouveau document qui est déposé. On peut envisager par le même biais d'extraire les propriétés de tout document déposé dans un répertoire et de l'envoyer par mail à un administrateur. Les idées ne manquent pas, à vous de jouer !

Conclusion

Disposer de tels outils ouvre la voie à l'intégration de fonction de GED de haut niveau dans toutes les applications, Web ou Desktop. C'est aussi un moyen simple de produire des documents OOXML loin des bricolages DDE, COM/DCOM, ActiveX ou autres pour faire de l'Automation. De plus les fichiers peuvent être manipulés sans que les applications équivalentes du pak Office ne soient installées, c'est un énorme avantage.

le projet (il faut installer le SDK OOXML of course) : PowerOPX.zip (2,91 kb)

Un éclairage sur les techniques d'accès aux données sous .NET

Depuis la sortie de .NET Microsoft n'arrête plus sa course folle ! La plupart des technologies publiées faisaient partie d'un plan presque totalement connu à l'avance, comme WPF, WCF etc. Il a fallu du temps pour qu'émerge ses "modules" de .NET car même le plus puissant des éditeurs de logiciels du monde ne peut pas releaser la totalité d'une montagne comme .NET en un seul morceau. S'il était clair que WPF serait la nouvelle gestion des interfaces utilisateurs et que Windows Forms n'était qu'un "os à ronger" en attendant, le foisonnement des technologies tournant autour des données n'était pas forcément visible ni prévisible il y a quelques années. Et même aujourd'hui savoir ce qui existe et comment s'en servir avec l'ensemble des autres technologies n'est pas forcément une mince affaire !

Un petit dessin valant tous les discours, voici un diagramme qui tourne sur les blogs américains de Microsoft et que j'ai en partie traduit pour vous, en espérant que cela vous aidera à y voir plus clair !

Quelques précisions pour certains acronymes ou noms de technologies :

[Faite un clic-droit sur l'image et copiez-la pour l'afficher en 100% dans Word ou autre ]

Powershell ou la ligne de commande objet sous .NET de Windows

Le shell de Windows nous renvoie aux temps préhistoriques où le PC avait un écran vert non graphique. Même les premières versions de Windows se lançaient aussi en ligne de commande. On ne parlait d'ailleurs pas de logiciels en "mode console" puisque c'était le mode normal... Le fameux DOS.

Avec les versions modernes de Windows est venu un autre temps, celui où Windows est devenu le DOS et où la ligne de commande n'est plus qu'une console qu'on appelle parfois et qui, une fois fermée, retourne à Windows, qu'on n'a pas quitté d'ailleurs... Inversion de tendance, mais le côté "rugueux", voire ésotérique de la console est resté.

Bien que le shell soit avec le temps devenu capable de faire des choses plus intelligentes il n'a finalement que peu évolué depuis MS-DOS.

Mais voici PowerShell !

PowerShell n'est pas un utilitaire freeware mais bien une extension Windows produite par Microsoft. Il s'agit de proposer une console (un shell) totalement objet fonctionnant sous .NET. Les commandes ne retournent plus des réponses textuelles mais des listes d'objets.

Certes, quand on tape un "dir" on obtient, grosso-modo, le même type d'affichage qu'avant. Mais cela est fort trompeur ! En réalité le "dir" (comme les autres commandes) retourne une liste d'objets dont on peut obtenir les méthodes, les propriétés. On peut aussi exécuter les méthodes de ces objets, remettre en forme la liste et bien d'autres choses encore !

Un exemple simple en quelques étapes :

  • obtenir la liste des services tournant sur la machine: get-service
  • obtenir cette liste et obtenir la classe des objets retournés ainsi que les membres de cette classe : get-service | get-member
  • obtenir le service de planification des tâches et savoir s'il peut être arrêté : (get-service schedule).CanStop
  • obtenir le service de planification des tâches et l'arrêter : (get-service schedule).stop()

etc...

Comme on le voit ici le "pipe" fonctionne toujours mais il sait passer les objets d'une commande à l'autre. On voit aussi qu'on peut obtenir un objet en particulier et invoquer ses méthodes ou accéder en lecture et en écriture à ses propriétés.

Le PowerShell c'est encore bien d'autres choses, des boucles ForEach par exemple, des Cmdlet (prononcer Command-let) des petites commandes toutes prêtes ou des alias permettant d'écrire moins de code. C'est aussi des scripts bien entendu ou l'accès à tous les drives de la machines même ceux plus abstraits comme Env (l'environnement) ou HKCU (la registry, clé du current user) dans laquelle on peut naviguer comme dans tout drive. Etc.

Le mieux c'est de voir par vous-même n'est-ce pas ? ... En téléchargeant cet outil sur la page du PowerShell Microsoft.

Bon shell

.. et Stay Tuned !

LINQ to {tapez ce que vous voulez ici}. Des providers à foison !

Vous connaissez LINQ to Object, LINQ to Dataset, LINQ to XML, etc... Microsoft livre déjà une large palette de fournisseurs de données (providers) pour LINQ. Dans sa grande sagesse Microsoft a aussi publié les spécifications (et des exemples) permettant à tous de développer des fournisseurs de données pouvant fonctionner avec LINQ. Cette ouverture extraordinaire permet d'interroger avec LINQ des données de toute sorte sans avoir besoin de les transformer au préalable.

Mais savez-vous qu'à ce jour il existe déjà plus d'une trentaine de providers LINQ ? Et que forcément certains vous rendrons des services inestimables, à condition d'en connaître l'existence... Vous pouvez même écrire vos propres providers LINQ ! Je vous conseille d'ailleurs cette page du Wayward blog qui propose une série de billets expliquant comment créer un tel provider.

Un exemple parmi tant d'autres pour illustrer le propos : LINQ To Amazon. Il permet tout simplement d'interroger directement Amazon pour sélectionner des livres selon autant de critères que nécessaire, et sans autre programmation qu'une requête LINQ. Fantastique non ? Un petit exemple pour concrétiser la chose :

var query =
  from book in new Amazon.BookSearch()
  where
    book.Title.Contains("ajax") &&
    (book.Publisher == "Manning") &&
    (book.Price <= 25) &&
    (book.Condition == BookCondition.New)
  select book;

 

Cool non ? LINQ to Amazon est présenté dans le livre LINQ in Action (que je vous conseille au passage) et vous pouvez accéder au blog de Fabrice qui le présente.

Mais cela n'est qu'un exemple, et il existe bien d'autres fournisseurs de données LINQ, en voici une liste (avec liens - shift clic pour les ouvrir dans une nouvelle fenêtre) :

Charlie Calvert, que les delphistes connaissent bien, et qui comme bon nombre des meilleurs a depuis longtemps choisi la voie .NET avec Microsoft, met à jour régulièrement cette liste qui est issue de son blog. Si vous lisez l'anglais, bookmarquez la page Links to LINQ de son blog qui, en plus de la liste des providers, fournit de nombreux liens en rapport avec cette technologie.

Conclusion

LINQ est une technologie fantastique dont je ne cesse de dire du bien (et d'utiliser avec bonheur dans la totalité des applications que j'écris), je ne peux imaginer utiliser demain ou dans 10 ans un langage qui n'implémentera pas une feature de même type. LINQ to "n'importe quoi" est la preuve que cette technologie est en plus ouverte et que seule notre imagination est la limite. Borland utilisait le slogan "the sky is the limit" durant ses grandes années de gloire. Microsoft ne le dit pas, mais la firme de Redmond rend ce rêve possible aujourd'hui...

 

Astuce du jour : déboguer du code sans écrire de code de test

Il arrive souvent (ou il devrait souvent arriver...) qu'on veuille tester rapidement du code. Par exemple vérifier qu'une méthode retourne bien le bon résultat selon deux ou trois variantes des paramètres d'entrée. Mais écrire du code de test à chaque fois, même si "on devrait" le faire tout le temps, n'est pas totalement conforme à la réalité. On a plus souvent la pression que la bride sur le collier et cela impose de travailler bien, mais vite ! Plus...

Un outil gratuit pour tester les requêtes LINQ

Qu'il s'agisse de LINQ to Object ou LINQ to SQL il serait bien agréable de pouvoir disposer d'une sorte de bloc-note pour tester ou mettre au point des requêtes, voire pour s'entraîner tout simplement. Pouvoir gérer les connexions aux bases de données, éventuellement envoyer et tester du SQL "de base" sur celles-ci serait la cerise sur la gâteau. Et bien cet outil existe, et en plus il est gratuit !

 

LINQPad, puisque c'est de lui qu'il s'agit, n'est pas vraiment une nouveauté absolue mais il y a fort à parier que nombre d'entre vous n'en ont jamais entendu parlé.

Cet outil a été développé conjointement à l'excellent ouvrage "C# 3.0 in a nutshell" de Joseph Albahari, un australien, qui par la diffusion gratuite de LINQPad tente une promo plutôt positive de son livre et de ses services de consulting (si on habite au pays des kangourous, of course).

J'aime personnellement cette idée de "pub positive" qui consiste à offrir de son temps et de son travail pour faire sa pub plutôt que de gaver les gens de bandeaux agaçants. C'est de la pub dans un esprit totalement anti-google (de la pub pour de la pub, partout, sans rien apporter à ceux qui la subissent), et il faut encourager ceux qui adoptent cette façon respectueuse de faire leur promotion. Achetez le livre de Joseph ! Fin de la paranthèse :-)

LINQPad est ainsi un super utilitaire. Il interprète du code C# ou VB et les requêtes LINQ to Object ou LINQ to SQL. Il autorise la connexion à des bases de données, offre un éditeur purement SQL en supplément, bien pratique, et il permet même d'ajouter ses propres DLL et ses propres espaces de noms pour qu'ils soient reconnus dans le code C# qu'on tape !

On peut dès lors utiliser LINQPad pour requêter des objets métiers complexes, un framework maison, un modèle LINQ to SQL, etc.. Il suffit d'ajouter les références.

Pour terminer, LINQPad est fourni avec de nombreux exemples qui sont autant de moyens de tester ses connaissances et d'apprendre les subtilités de LINQ. Utilisé conjointement à ma version des "101 exemples LINQ" de Microsoft, LINQPad devient un fantastique outil d'auto-formation.

Pour télécharger le produit et avoir accès aussi aux forums, aux vidéos de démo, et plein d'autres choses, aller sur la page de LINQPad !

Bon Dev...

Et Stay Tuned !

 

Simplifier les gestionnaires d'événement grâce aux expressions Lambda

Les expressions Lambda ont été introduites dans C# 3.0. Utilisées correctement, tout comme LINQ to Object, elles permettent une grande simplification du code entraînant dans un cercle vertueux une meilleure lisibilité de ce dernier favorisant maintenabilité et fiabilité de ce même code. Il n'y a donc aucune raison de rester "frileux" vis à vis de cette nouveauté syntaxique comme encore trop de développeurs que je rencontre dans mes formations ou ailleurs.

Pour démontrer cette souplesse, voici un petit exemple qui valide un document XML en fonction d'un schéma.

La méthode Validate() de la classe XDocument attend en paramètre un delegate de type ValidationEventHandler. Dans un code très court il n'est pas forcément judicieux de déclarer une méthode juste pour passer son nom en paramètre à Validate(). Les "sous procédures" ou procédures imbriquées de Pascal n'existent pas en C# et l'obligation de déclarer à chaque fois des méthodes private pour décomposer la moindre action est une lourdeur syntaxique de ce langage dont on aimerait se passer parfois (une méthode même private est visible par toutes les autres méthodes de la classe ce qui n'est pas toujours souhaitable. Seules les méthodes imbriquées de Pascal sont des "méthodes privées de méthodes").

En fin de billet vous trouverez d'ailleurs le lien vers un autre billet dans lequel j'explique comment utiliser les expressions Lambda en les nommant pour retrouver la souplesse des procédures imbriquées. Même si "l'astuce" présentée ici peut y ressembler dans l'esprit, dans la pratique les choses sont assez différentes puisque nous n'utiliserons pas une expression nommée.

Revenons à l'exemple, il s'agit de valider un document XML à partir d'un schéma. Et de le faire de la façon la plus simple possible, c'est à dire en évitant l'écriture d'un delegate, donc en utilisant directement une expression Lambda en paramètre de Validate().

Supposons que nous ayons déjà le schéma (variable schema) et le document XML (variable doc), l'appel à Validate pourra donc s'écrire :

doc.Validate(schema,(obj, e) => errors += e.Message + Environment.NewLine);

"errors" est déclarée comme une chaîne de caractères. A chaque éventuelle erreur détectée par la validation l'expression concatène le message d'erreur à cette dernière. En fin de validation il suffit d'afficher errors pour avoir la liste des erreurs. Mais cela n'est qu'un exemple d'utilisation de l'expression Lambda. Ce qui compte c'est bien entendu de comprendre l'utilisation de cette dernière en place et lieu d'un delegate de tout type, ici ValidationEventHandler d'où les paramètres (obj,e) puisque ce delegate est déclaré de cette façon (un objet et un argument spécifique à cet handler).

C'est simple, nul besoin de déclarer un gestionnaire d'événement donc une méthode avec un nom et une visibilité. On évite que cette méthode soit réutilisée dans le code de la classe considérée (si elle existe on est tenté de la réutiliser mais sa stratégie d'écriture n'est pas forcément adaptée à une telle utilisation d'où possible bug), etc. Que des avantages donc.

Pour plus d'information vous pouvez lire mon article sur les nouveautés syntaxiques de C# 3.0 ainsi que mon billet montrant comment retrouver en C# le bénéfice des procédures imbriquées de Pascal grâce aux expressions Lambda.

Si vous voulez jouez avec l'exemple, vous pouvez télécharger le projet VS 2008 qui montre tout cela : lambda.zip (21,71 kb)