Visual Studio 2005 : un exemple d'utilisation des fonctions anonymes en C# 2.0
Par Frédéric Colin, posté le 09/02/2005
Profil : Développeur | Niveau : Intermédiaire (200)
1 Introduction
Parmi les très nombreuses nouveautés offertes par Visual C# 2.0, les méthodes anonymes couplées aux listes génériques peuvent offrir des services forts pratiques. Cet article permet de vous montrer deux exemples précis :
· Le tri sur n'importe quel champ d'un élément d'une liste générique
· La recherche sur n'importe quel champ pour une valeur donnée d'un champ d'une liste générique
À noter que j'ai utilisé la "Reflection" .NET afin de rendre certaines tâches un peu plus génériques.
2 Objectif fonctionnel
La solution est composée d'un seul projet C# Windows Forms dans lequel les couches basiques d'une application multi-niveaux sont représentées dans des sous-espaces de nom dédiés. L'objectif avoué étant :
· de récupérer la classique liste des employés de la base exemple Northwind de SQL Server 2000,
· de l'afficher dans une grille,
· de proposer une recherche et un tri par colonne.
3 Description technique
Voici les espaces de noms retenus dans le cadre de ce petit exemple :
· Sample : espace de nom principal de l'exemple contenant la fenêtre de l'application
o .Business : espace de nom contenant la classe métier permettant de récupérer la liste des employés
o .Data : espace de nom contenant la classe donnée, chargée d'exécuter la requête SQL et de créer la liste générique
o .Common.Entities : espace de nom contenant la classe permettant de définir précisément l'entité employé.
La couche Common contient une seule classe représentant l'entité employé :
Points intéressants à regarder dans le code de cette classe : N/A.
La couche Data contient une seule classe permettant de requêter la base :
Points intéressants à regarder dans le code de cette classe :
· utilisation d'un "provider factory" pour l'accès aux données (à noter que le provider est codé en dur (c'est bien entendu mal) et qu'il serait intéressant de le paramétrer (« System.Data.SqlClient »)).
· Le cast par une méthode générique permettant de gérer les valeurs « NULL » issues de la base.
La couche Business contient une classe qui permet de récupérer la liste générique des employés (ou bien un employé unique en fonction de son ID) :
Points intéressants à regarder dans le code de cette classe :
· Utilisation d'un type Nullable comme paramètre de la méthode Select.
L'interface commentée du formulaire est la suivante :
Points intéressants à regarder dans le code de ce formulaire Windows :
· Méthode anonyme de tri générique
· Méthode anonyme de recherche générique
· Dans le tri : utilisation de la « Reflection .NET » afin de récupérer la valeur d'un champ et la comparer à la valeur d'un autre champ dans le délégué utilisé par le tri
· Dans la recherche : utilisation de la « Reflection .NET » pour récupérer la valeur d'une propriété et la comparer à la valeur saisie par l'utilisateur en fonction de l'opérateur de comparaison sélectionné.
Comme vous pourrez le constater dans le code du formulaire, une méthode anonyme est une méthode non nommée (!) et définie sur son emplacement d'utilisation. En règle générale, une méthode anonyme peut-être définie à chaque fois qu'un délégué est attendu.
Par exemple pour notre méthode de recherche, la liste générique List possède une méthode « FindAll » dont une des surcharges admet en paramètre le délégué permettant de gérer si l'employé courant rempli le critère de recherche voulu.
1: List searchedEmployees =2: lst.FindAll(3: delegate(Sample.Common.Entities.EmployeeInfo theEmp)4: {5: object theValue = theType.GetProperty(textBox1.Text).GetValue(theEmp, null);6: Int32 res = (7: ((IComparable)theValue)8: .CompareTo(9: Convert.ChangeType(textBox2.Text, theValue.GetType()10: )11: )12: );13: // Gestion de l'oprateur de recherche14: switch ( comboBox1.Text )15: {16: case "=" :17: return res == 0;18: case ">" :19: return res > 0;20: default:21: return res < 0;22: }23: }24: );
Enfin, une méthode anonyme a accès aux variables déclarées dans son bloc de définition.
4 Conclusion
Bien entendu, cette façon de faire ne doit pas systématiquement remplacer une requête base pour un filtrage et/ou un tri. Il est souvent plus performant de déléguer ces tâches au moteur de notre SGBD favori. Mais, c'est parfois utile lorsque l'on ne souhaite justement pas requêter à nouveau la BD pour chaque ordre de tri et/ou chaque recherche.
À titre d'information, voici les temps d'exécution moyen en mode Release pour un tri (colonne ReportsTo) et une recherche (colonne ReportTo et valeur = 2) en augmentant sensiblement le nombre d'enregistrements. Vous noterez la linéarité des deux progressions (l'une pour le tri, l'autre pour la recherche). Dans ces exemples, j'utilise pleinement la « reflection .NET » et cette dernière a bien entendu un impact important sur les temps d'exécution :
Cet article a été réalisé sur les versions suivantes :
Framework .NET version 2.0.50215
Visual Studio 2005 version 8.0.50215.44 (beta2.050215-4400)
Après avoir dirigé la Gestion de la Production à Bewise pendant de nombreuses années, Frédéric a rejoint Vertice, une société du groupe éditrice de la gamme Nova et spécialisée dans la 3D interactive. Partisan d’une 3D interactive mais aussi démonstrative et utile, il s’attache à illustrer ses propos via son blog. Malgré ce changement de poste, il n’en a pas oublié ses racines de développeur et continue de participer à la communauté .NET en publiant des articles sur la conception d’Architectures pragmatiques et distribuées. Retombé depuis peu dans les musiques de type « Métal » pour le plus grand malheur de ses collègues de bureau, il n’en reste pas moins éclectique dans ses goûts musicaux !



