Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

C# 3.0 : Les types anonymes en détail

Les types anonymes sont ma nouveauté préférée de C# 3.0. Ils sont très intuitifs à utiliser, mais tout le monde ne connait pas leurs caractéristiques exactes. Je me charge donc de les rappeler.

  • Vous pouvez déclarer une variable locale de type anonyme de la façon suivante :

var variableTypeAnonyme = new { FirstName = "Flavien", Age = 23, DateOfBirth = new DateTime(1984, 11, 15) };

Le compilateur va donc créer une classe générique qui aura les propriétés correspondantes, et dont les types sont inférés grâce à l'expression d'initialisation (ici, FirstName de type string, Age de type int et DateOfBirth de type DateTime).

Etant donné que le type n'a pas de nom, l'utilisation du mot-clé var est obligatoire. Il est également obligatoire pour les types génériques dont un des types paramètres est un type anonmyme (par exemple IEnumerable<T> lorsque T est un type anonyme).

  • Pour que deux variables de types anonymes soient de même type, il faut que ces deux variables aient été déclarées avec les mêmes propriétés, mêmes types pour chacune des propriétés et que les propriétés soient déclarées dans le même ordre. Par exemple, ces deux variables ne sont pas de même type (les propriétés sont inversées) :

var variableTypeAnonyme = new { FirstName = "Flavien", Age = 23, DateOfBirth = new DateTime(1984, 11, 15) };
var variableTypeAnonyme = new { FirstName = "Britney", DateOfBirth = new DateTime(1981, 12, 2), Age = 26 };

  • Les variables de type anonyme sont immutables, c'est à dire que les propriétés n'ont pas de set. Il n'est plus possible de les modifier après l'initialisation.
  • Les variables de type anonyme sont confinées dans la méthode dans laquelle elles sont définies, puisqu'on ne peut pas retourner ou passer en argument une variable de type "var". Le seul moyen de retourner une variable de type anonyme est de la convertir en object, et il sera par la suite impossible de reconvertir la variable dans son type d'origine puisque il est interdit de convertir vers un type anonyme. Retourner une variable de type anonyme est donc inutile à moins d'utiliser la réflexion. Cela évite la propagation incontrôlée des types anonymes.
  • Il n'est pas possible d'ajouter de méthode aux types anonymes, ceux-ci sont juste des containeurs de données.
  • La méthode ToString est surchargée et utilise la méthode ToString de chacun des attributs. Le format est le suivant :

{ FirstName = Flavien, Age = 23, DateOfBirth = 11/15/1984 12:00:00 AM }

  • Egalité : La méthode Equals est surchargée de telle façon que deux instances du même type anonyme sont égales si toutes leurs propriétés sont égales, au sens de la comparaison par défaut des types des propriétés. Donc les deux instances suivantes seront considérées comme égales :

var variableTypeAnonyme = new { FirstName = "Flavien", Age = 23, DateOfBirth = new DateTime(1984, 11, 15) };
var variableTypeAnonyme2 = new { FirstName = "Flavien", Age = 23, DateOfBirth = new DateTime(1984, 11, 15) };

La méthode GetHashCode est également surchargée pour refléter cette égalité. Le code de hashage est par ailleurs construit de façon intelligente pour tenir compte de tous les membres. Donc les types anonymes peuvent être utilisés efficacement comme clés dans un Dictionary par exemple.

Le compareur par défaut (Comparer<T>.Default) d'un type anonyme est donc tout à fait utilisable pour effectuer une comparaison profonde (les membres sont comparés deux à deux) de deux instances du même type anonyme.

La conséquence de ceci est qu'il est possible d'utiliser un type anonyme comme clé dans une clause join ou group dans une expression LINQ. Cela peut être utile si vous souhaitez par exemple grouper les résultats d'une requête en utilisant deux critères à la fois :

var result = from person in list
   
group person by new { LastName = person.LastName, YearOfBirth = person.DateOfBirth.Year };

Les types anonymes n'implémentent aucune méthode de comparaison (IComparer) de supériorité ou infériorité, il est donc impossible de les utiliser dans une clause orderby.

Pour plus d'infos sur les types anonymes : http://msdn2.microsoft.com/en-us/library/bb397696(VS.90).aspx.

Publié lundi 10 décembre 2007 14:36 par RaptorXP
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# re: C# 3.0 : Les types anonymes en détail

http://weblogs.asp.net/leftslipper/archive/2007/09/24/using-c-3-0-anonymous-types-as-dictionaries.aspx c'est utilisé avec ASP.net MVC et je n'aime pas cette utilisation des types anonymes. J'aurais préféré un initialiseur de dictionnaire.

On apprend également dans les commentaires que C#4 permettra d'écrire ça :

var o = new : IHtmlLinkParams { text = "Some Text", customProp = "some value" }

lundi 10 décembre 2007 21:45 by cyril

# re: C# 3.0 : Les types anonymes en détail

Je trouve que les deux se valent. L'avantage d'un type anonyme c'est que l'initialisation est plus rapide qu'un dictionnaire, par contre après ASP.NET est obligé d'utiliser la reflexion.

Par contre en WPF par exemple, le même genre de mécanisme existe pour le DataBinding, sauf qu'il n'est pas possible d'utiliser un dictionnaire, donc ici les types anonymes tombent à point.

mardi 11 décembre 2007 11:17 by RaptorXP

# re: C# 3.0 : Les types anonymes en détail

static void Main(string[] args)

{

   var sb = new StringBuilder();

   var sw = Stopwatch.StartNew();

   for (int i = 0; i &lt; 10000; i++)

   {

       var d = new Dictionary

<String, String="">() {

           { "key1", "value1" },

           { "key2", "value2" },

           { "key3", "value3" },

           { "key4", "value4" },

           { "key5", "value5" }

       };

       foreach (var key in d.Keys)

       {

           sb.Append(key).Append(d[key]);

       }

   }

   Console.WriteLine(sw.ElapsedMilliseconds);

   sb = new StringBuilder();

   sw = Stopwatch.StartNew();

   for (int i = 0; i &lt; 10000; i++)

   {

       var d = new

       {

           key1 = "value1",

           key2 = "value2",

           key3 = "value3",

           key4 = "value4",

           key5 = "value5"

       };

       foreach (var pi in d.GetType().GetProperties()) {

           sb.Append(pi.Name).Append(pi.GetValue(d, null));

       }

   }

   Console.WriteLine(sw.ElapsedMilliseconds);

}

44ms pour le dico et 450ms pour la reflection

Par contre c'est vrai que si on fait pas la lecture on a 16ms et 0. Mais à quoi sert un objet si on peut pas le lire ? ;-)

Donc pour moi c'est une mauvaise approche. Si ms veut utiliser les types anonymes de cette manière il faut absolument optimiser la reflection.

De plus, il faut que notre type anonyme puisse avoir une interface (comme proposé ci dessus) voir pourquoi pas hériter d'une classe. Genre new AbstractClass {AbstractProp="truc", NewProp="pouet"}. Ainsi on pourra utiliser les extensions de méthodes et l'héritage.

En conclusion je me rend compte que les types anonymes sont pas encore finalisé :-)

mardi 11 décembre 2007 11:40 by cyril

# re: C# 3.0 : Les types anonymes en détail

Comme je le dis plus haut, ils ne sont pas fait pour être retournés par une fonction. Leur utilisation principale est d'être confinés dans la méthode.

Le problème avec la reflexion ca a rien a voir avec les types anonymes. Avant, on pouvait déjà renvoyer des objets pour un ObjectDataSource par exemple, et ASP.NET utilise la reflection pour lire le contenu des propriétés. ASP.NET, même avant les types anonymes utilisait la reflexion à gogo. La différence, c'est que maintenant on n'a plus besoin de créer explicitement un type trivial qui sert juste à stocker quelques valeurs.

Dans le blog, l'auteur donne juste un exemple d'utilisation des types anonymes mais les deux approches sont possibles. L'approche C# 2.0 de créer une classe triviale avec quelques propriétés est aussi possible, mais elle utilise également la reflection.

mardi 11 décembre 2007 15:04 by RaptorXP
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01