septembre
2008
Une des grandes nouveautés de C# 3 est la possibilité des créer des types anonymes. Un type anonyme offre la possibilité de composer des types « temporaires » avec une ou plusieurs propriétés en lecture seule. Cette nouveauté s’avère extrêmement efficace avec Linq car on va pouvoir interroger des sources de données et récupérer uniquement les informations dont on a besoin au travers d’objets anonymes.
Durant ce petit article, nous verrons très brièvement ce qu’est un type anonyme pour ensuite tenter de renvoyer un type anonyme à partir d’une méthode.
Prenons un exemple simple qui va être de récupérer la liste des processus triés par nom.
var query = from proc in System.Diagnostics.Process.GetProcesses() foreach (var item in query) |
Évidemment, on est forcé de récupérer un objet de type « System.Diagnostics.Process » avec toutes les informations qui l’accompagne alors que dans notre cas, le nom de processus et son id nous auraient suffit. C’est là qu’intervient la notion de type anonyme :
var query = from proc in System.Diagnostics.Process.GetProcesses() foreach (var item in query) |
Comme vous pouvez le voir, un type anonyme est créé en utilisant l’opérateur new suivi d’accolades pour initialiser les différentes propriétés que l’on désire voir apparaître dans son objet anonyme. Dans la boucle foreach, on s’aperçoit que « item » propose bien deux propriétés « Id » et « ProcessName« . Chose importante à noter, « item » représente un type anonyme, il n’est donc pas possible de le nommer… Il faut donc passer par l’utilisation du mot clé var qui déduira le type automatiquement.
Pour vous en convaincre que « item » n’est pas de type « System.Diagnostics.Process« , voici la preuve en image :
La compilateur a donc effectivement créé un type avec les propriétés adéquates. Le type de ces mêmes propriétés a été au passage inféré grâce à l’initialisation. Bien sûr, rien ne vous empêche de nommer vos noms de propriétés comme vous le désirez :
var query = from proc in System.Diagnostics.Process.GetProcesses() foreach (var item in query) |
Si on jette un petit coup d’oeil au niveau du code compilé avec Reflector (http://www.red-gate.com/products/reflector/), on remarque qu’une classe générique a été créée automatiquement pour représenter notre type anonyme.
Cette nouveauté de types anonymes n’est donc possible que grâce à un changement du compilateur C#, le CLR (Common Language Runtime) n’a en aucun cas été modifié.
Maintenant que vous avons mis les choses à plat sur ce qu’est un type anonyme, penchons nous sur le sujet de ce billet et qui est de savoir comment il est possible de renvoyer un type anonyme à partir d’une méthode.
Comme je l’ai dit tout à l’heure, le type anonyme n’ayant pas de nom, on est obligé de passer par le mot clé var pour manipuler de tels objets. Si on désire encapsuler dans une méthode notre code qui permet de récupérer cette fois-ci le premier processus, cette méthode sera obligée de renvoyer un objet de type « System.Object« . Effectivement, peu importe qu’on ait un type anonyme ou pas, tous dérive de la classe « System.Object« .
static System.Object GetProcesses() |
Seulement petit problème, on perd l’intellisense en ayant converti notre type anonyme en « System.Object« , donc impossibilité de récupérer les valeurs dans les propriétés « ProcessID » et « Name« . Solution que vous allez de suite me proposer : La réflexion ! Et vous avez raison sur le point que ça fonctionnera mais niveau performance, on sera loin… En fait, il y a une solution beaucoup plus simple et c’est en allant voir le code compilé que nous en aurons la preuve !
Tout d’abord, nous avons notre objet anonyme de la méthode « GetProcesses » qui est composé des éléments suivants :
- Une propriété « ProcessID » de type System.Int32
- Une propriété « Name » de type System.String
Maintenant, nous allons faire un test en créant exactement le même type anonyme mais en dehors de cette méthode, par exemple dans la méthode « Main » :
var anonymousType = new { ProcessID = 0, Name = « » }; |
Et si on vérifie le code compilé, on s’aperçoit que le compilateur a détecté que dans notre programme, il y avait deux types anonymes exactement les mêmes (même noms de propriétés, dans le même ordre et avec le même type) : il a donc tout simplement généré une et une seule classe pour ces deux types anonymes identiques.
A partir de cette idée, on peut très facilement implémenter une méthode générique qui prendra en paramètres :
- L’instance de notre objet anonyme de type « System.Object«
- Et une autre instance « bidon » de ce même type mais passée de manière générique
Une simple conversion et le tour est joué !
class Program static System.Object GetProcesses() static A CastAnonymousObject<A>(object anomymousObject, A anonymousType) |
Simple non ?
Déménagement
Next Microsoft CEO
Articles récents
- Changement d’adresse de ce blog
- Article : les nouveautés de C# 5.0
- Modèle Entity Framework généré avec SQL Server 2008 et utilisé sous SQL Server 2005
- Les photos, vidéos et cadeaux des TechDays 2011
- La première journée en ligne sur TechDays TV
- Suivez les TechDays 2011 comme si vous y étiez sur la chaîne TechDays TV
- Téléchargez le programme des conférence des TechDays 2011
- Dernier jour des TechDays = plus de chance de remporter des cadeaux sur le stand de dvp !
- Venez à notre rencontre lors des TechDays 2011
- Les flux à ne pas rater lors des TechDays 2011
- Les TechDays 2011 s’invite sur votre smartphone Windows Phone 7
- Exclu des cadeaux du concours Developpez.com lors des TechDays 2011
- Ouverture de la galerie d’images sur notre site des TechDays
- Partagez votre expérience des Microsoft TechDays
- Grand concours Microsoft “FAN des TechDays 2011” : épisode 2 !
- Mettez-vous aux couleurs des TechDays 2011 !
- Developpez.com aux TechDays 2011
- Le Challenge Azure 2010 est fini !
- Suivez la keynote de la pdc10 en direct sur internet à 18h !
- MVP Visual C# 2010 – 2011 !!!