| ||||||
auteur : Jérôme Lambert | ||||||
C# 3.0 a introduit un nouveau mot clé permettant de déclarer des variables sans pour autant spécifier explicitement leur type. Ce nouveau mot clé est "var".
Comme vous pouvez le voir, l'utilisation de " var " est très simple : une fois la variable déclarée, il vous faut l'initialiser directement. Le compilateur va inférer automatiquement le type de votre variable.
Chose importante à ne pas confondre, var est différent de " Variant " de VB qui permet de définir le type de votre variable quand vous le désirez. Ici, c'est le compilateur qui va inférer le type de votre variable sur base de l'expression d'initialisation que vous allez spécifier.
Evidemment, tout n'est pas permis et voici les règles à ne pas oublier :
Malgré cette nouveauté du langage, Microsoft recommande d'utiliser var uniquement si cela s'avère nécessaire. Une utilisation trop excessive de var risquerait de complexifier votre code inutilement. Par exemple, les types anonymes sont le cas parfait pour l'utilisation de var.
| ||||||
lien : ![]() |
| |||||||||
auteur : Jérôme Lambert | |||||||||
Initialiseurs d'objets
L'initialiseur d'objet vous permet d'instancier une classe tout en initialisant les champs et propriétés de cette classe que vous désirez, le tout en une seule instruction.
Initialiseurs de collections
L'initialiseur de collection fonctionne sur le même principe mais pour les collections.
Vous pouvez même aller plus loin en utilisant l'initialiseur d'objet en même temps que l'initialisation de votre collection :
| |||||||||
lien : ![]() |
| |||
auteur : Jérôme Lambert | |||
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.
Résultat :
Jérôme Lambert est né le samedi 25 février 1984
Dans l'exemple précédent, on peut voir que j'ai créé un type qui n'existe pas, c'est pourquoi je suis obligé de déclarer ma variable "anonymousType" avec le mot clé "var" qui permet un typage implicite de variable. Pour créer un type anonyme, il suffit d'utiliser le mot clé "new" suivi d'accolades qui contiendront les propriétés. Mon objet anonyme contient deux propriétés que j'ai nommé "Name" et "Birthday". Etant donné que j'ai initalisé mes deux propriétés, le compilateur est capable de déduire le type de ces deux propriétés (System.String pour la propriété "Name" et System.DateTime pour la propriété "Birthday").
Comme je l'ai dit précédemment, l'utilisation des types anonymes s'avère extrêmement intéressante avec les requêtes Linq. Prenons l'exemple de la liste des processus de votre ordinateur : si on désire récupérer les processus commençant par la lettre "A", on peut écrire tout simplement la requête suivante :
Le problème avec cette requête, c'est qu'on est obligé de récupérer une collection d'objets de type System.Diagnostics.Process. Or comme on peut voir dans la boucle foreach, je n'ai besoin que du nom du processus et son ID. C'est là qu'interviennent les types anonymes car je vais pouvoir précifier que chaque résultat doit être représenté par un type qui contient uniquement les valeurs dont j'ai besoin, c'est à dire le nom du processus et son ID.
Petite remarque et ce n'est pas une faute, je n'ai pas précisé le nom des propriétés dans mon objets anonymes. De ce fait, le compilateur a automatiquement créé des propriétés qui ont le même noms que les propriétés utilisées pour initialiser mon objet anonyme.
| |||
lien : ![]() |
| ||||||
auteur : Jérôme Lambert | ||||||
Prenons un exemple simple qui va être de récupérer la liste des processus triés par nom.
É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 :
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 :
Si on jette un petit coup d'oeil au niveau du code compilé avec Reflector ( ![]() ![]()
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 cette question 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érivent de la classe "System.Object".
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 :
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" :
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 :
Une simple conversion et le tour est joué !
| ||||||
lien : ![]() lien : Lien vers l'article original |
| ||||||
auteur : Jérôme Lambert | ||||||
Les méthodes d'extension sont des méthodes statiques qui vous permettent d'étendres les types existants sans avoir besoin de créer un type dérivé ou bien modifier/recompiler le type original. Au final, il n'y a aucune différence entre appeler une méthode d'extension ou une méthode qui existent réellement dans le type concerné. Les méthodes d'extension sont considérées comme des méthodes d'instance de type pour le développeur.
Pour vous montrer un exemple concrêt, nous allons créer une méthode d'extension pour le type System.String qui permettra de convertir un string en System.Int32 si cela s'avère possible, dans le cas contraire nous lancerons une exception de type System.FormatException.
Et non, ce n'est pas encore ça une méthode d'extension. Le code ci-dessous est ce que vous auriez écrit avec C# 2.0. Par contre le code ci-dessous illustre l'utilisation d'une méthode d'extension :
Comme vous pouvez le remarquer, j'ai pu appeler la méthode "ToInt32" directement sur mon type System.String. Cela est possible grâce au mot clé this suivi du type concerné en paramètre à la méthode ToInt32. Le premier paramètre d'une méthode d'extension représente donc le type qui est concerné et la variable est tout simplement l'instance qui a appelé notre méthode d'extension.
Cependant, les méthodes d'extension sont utilisables aussi avec des paramètres. Par exemple, on pourrait "améliorer" notre méthode d'extension pour qu'elle puisse forcer une conversion, c'est à dire que si une conversion du type System.String vers System.Int32 n'est pas possible, on ne lancera pas d'exception pour renvoyer tout simplement la valeur 0.
Pour ceux qui ont déjà touché à C# 3.0, vous avez surement déjà vu une série de nouvelles méthodes lorsque vous manipulez des collections impplémentant l'interface System.Collections.Generic.IEnumerable<T>, exemple Where, Select, OrderBy, etc. Ce sont tout simplement des méthodes d'extensions appelées plus particulièrement des opérateurs de requête standard Linq (Pour en savoir plus sur les opérateurs de requêtes : ![]()
Pour utiliser les méthodes d'extension, il y a quelques contraintes à respecter :
| ||||||
lien : ![]() lien : ![]() |
Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.