Types anonymes (Visual Basic)

Visual Basic prend en charge les types anonymes, qui vous permettent de créer des objets sans écrire de définition de classe pour le type de données. À la place, le compilateur se charge de générer une classe. La classe ne possède pas de nom utilisable, hérite directement de Object et contient les propriétés que vous spécifiez lors de la déclaration de l'objet. Étant donné que le nom du type de données n'est pas spécifié, ce dernier est dénommé type anonyme.

L'exemple suivant déclare et crée une variable product comme instance d'un type anonyme possédant deux propriétés, Name et Price.

' Variable product is an instance of a simple anonymous type.
Dim product = New With {Key .Name = "paperclips", .Price = 1.29}

Une expression de requête utilise des types anonymes pour associer des colonnes de données sélectionnées par une requête. Vous ne pouvez pas définir le type du résultat à l'avance, parce que vous ne pouvez pas prédire les colonnes sélectionnées par une requête particulière. Les types anonymes vous permettent d'écrire une requête qui sélectionne n'importe quel nombre de colonnes, dans n'importe quel ordre. Le compilateur crée un type de données qui correspond aux propriétés et à l'ordre spécifiés.

Dans les exemples suivants, products est une liste d'objets de produit, possédant chacun de nombreuses propriétés. La variable namePriceQuery contient la définition d'une requête qui, lorsqu'elle est exécutée, retourne une collection d'instances d'un type anonyme possédant deux propriétés, Name et Price.

Dim namePriceQuery = From prod In products
                     Select prod.Name, prod.Price

La variable nameQuantityQuery contient la définition d'une requête qui, lorsqu'elle est exécutée, retourne une collection d'instances d'un type anonyme possédant deux propriétés, Name et OnHand.

Dim nameQuantityQuery = From prod In products
                        Select prod.Name, prod.OnHand

Pour plus d'informations sur le code créé par le compilateur pour un type anonyme, consultez Définition du type anonyme (Visual Basic).

Avertissement

Le nom du type anonyme, généré par le compilateur, peut varier de compilation en compilation. Votre code ne doit pas utiliser ou reposer sur le nom d'un type anonyme, car ce nom est susceptible de changer lorsqu'un projet est recompilé.

Déclaration d'un type anonyme

La déclaration d'une instance d'un type anonyme utilise une liste d'initialiseurs pour spécifier les propriétés du type. Vous pouvez spécifier uniquement des propriétés lorsque vous déclarez un type anonyme et pas d'autres éléments de classe tels que les méthodes ou événements. Dans l'exemples suivant, product1 est une instance d'un type anonyme possédant deux propriétés : Name et Price.

' Variable product1 is an instance of a simple anonymous type.
Dim product1 = New With {.Name = "paperclips", .Price = 1.29}
' -or-
' product2 is an instance of an anonymous type with key properties.
Dim product2 = New With {Key .Name = "paperclips", Key .Price = 1.29}

Si vous désignez des propriétés comme propriétés de clé, vous pouvez les utiliser pour comparer l'égalité de deux instances de type anonyme. Toutefois, les valeurs des propriétés de clé ne peuvent pas être modifiées. Pour plus d'informations, consultez la section Propriétés de clé, plus loin dans cette rubrique.

Notez que la déclaration d'une instance d'un type anonyme est comparable à la déclaration d'une instance d'un type nommé à l'aide d'un initialiseur d'objet :

' Variable product3 is an instance of a class named Product.
Dim product3 = New Product With {.Name = "paperclips", .Price = 1.29}

Pour une comparaison plus détaillée des déclarations de types nommés et anonymes, consultez Comparaison entre types nommés et types anonymes (Visual Basic).

Pour plus d'informations sur d'autres façons de spécifier des propriétés de type anonymes, consultez Comment : déduire les types et les noms de propriétés dans des déclarations de types anonymes (Visual Basic).

Propriétés de clé

Les propriétés de clé et les propriétés ne correspondant pas à une clé présentent des différences fondamentales :

  • Seules les valeurs des propriétés de clé sont comparées pour déterminer si deux instances sont égales.

  • Les valeurs des propriétés de clé sont en lecture seule et ne peuvent pas être modifiées.

  • Seules les valeurs des propriétés de clé sont incluses dans l'algorithme de code de hachage généré par le compilateur pour un type anonyme.

Égalité

Les instances de types anonymes sont égales uniquement si elles sont des instances du même type anonyme. Le compilateur traite deux instances comme instances du même type si elles remplissent les conditions suivantes :

  • Elles sont déclarées dans le même assembly.

  • Leurs propriétés sont déclarées dans le même ordre, avec les mêmes noms et les mêmes types déduits. Les comparaisons de nom ne respectent pas la casse.

  • Les mêmes propriétés de chaque déclaration sont marquées comme propriétés de clé.

  • Au moins une propriété de chaque déclaration est une propriété de clé.

Une instance d'un type anonyme qui ne possède pas de propriétés de clé est uniquement égale à elle-même.

' prod1 and prod2 have no key values.
Dim prod1 = New With {.Name = "paperclips", .Price = 1.29}
Dim prod2 = New With {.Name = "paperclips", .Price = 1.29}

' The following line displays False, because prod1 and prod2 have no
' key properties.
Console.WriteLine(prod1.Equals(prod2))

' The following statement displays True because prod1 is equal to itself.
Console.WriteLine(prod1.Equals(prod1))

Deux instances d'un type anonyme identique sont égales si les valeurs de leurs propriétés de clé sont égales. Les exemples suivants illustrent comment l'égalité est testée.

Dim prod3 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod4 = New With {Key .Name = "paperclips", Key .Price = 1.29}
' The following line displays True, because prod3 and prod4 are
' instances of the same anonymous type, and the values of their
' key properties are equal.
Console.WriteLine(prod3.Equals(prod4))

Dim prod5 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim prod6 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays False, because prod5 and prod6 do not 
' have the same properties.
Console.WriteLine(prod5.Equals(prod6))

Dim prod7 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 24}
Dim prod8 = New With {Key .Name = "paperclips", Key .Price = 1.29,
                      .OnHand = 423}
' The following line displays True, because prod7 and prod8 are
' instances of the same anonymous type, and the values of their
' key properties are equal. The equality check does not compare the
' values of the non-key field.
Console.WriteLine(prod7.Equals(prod8))

Valeurs en lecture seule

Les valeurs des propriétés de clé ne peuvent pas être modifiées. Par exemple, dans prod8 dans l'exemple précédent, les champs Name et Price sont en lecture seule dans read-only, mais OnHand peut être modifié.

        ' The following statement will not compile, because Name is a key
        ' property and its value cannot be changed.
        ' prod8.Name = "clamps"

        ' OnHand is not a Key property. Its value can be changed.
        prod8.OnHand = 22

Types anonymes issus d'expressions de requête

Les expressions de requête ne requièrent pas toujours la création de types anonymes. Lorsque cela est possible, ils utilisent un type existant pour contenir les données de colonne. Cela se produit lorsque la requête retourne des enregistrements entiers de la source de données ou un seul champ de chaque enregistrement. Dans les exemples de code suivants, customers est une collection d'objets d'une classe Customer. La classe possède de nombreuses propriétés et vous pouvez en inclure une ou plusieurs dans le résultat de la requête, dans n'importe quel ordre. Dans les deux premiers exemples, aucun type anonyme n'est requis parce que les requêtes sélectionnent les éléments de types nommés :

  • custs1 contient une collection de chaînes, parce que cust.Name est une chaîne.

    Dim custs1 = From cust In customers
                 Select cust.Name
    
  • custs2 contient une collection d'objets Customer, parce que chaque élément de customers est un objet Customer et l'élément entier est sélectionné par la requête.

    Dim custs2 = From cust In customers
                 Select cust
    

Toutefois, les types nommés appropriés ne sont pas toujours disponibles. Vous pouvez sélectionner des noms de client et des adresses pour un usage particulier, les numéros et les emplacements d'ID de client pour un autre, et noms de client, les adresses et les historiques de commande pour un troisième. Les types anonymes vous permettent de sélectionner n'importe quelle combinaison de propriétés, dans n'importe quel ordre, sans déclarer d'abord un nouveau type nommé pour contenir le résultat. À la place, le compilateur crée un type anonyme pour chaque compilation de propriétés. La requête suivante sélectionne uniquement le nom du client et le numéro d'ID de chaque objet Customer dans customers. Par conséquent, le compilateur crée un type anonyme qui contient uniquement ces deux propriétés.

Dim custs3 = From cust In customers
             Select cust.Name, cust.ID

Les noms et les types de données des propriétés du type anonyme sont transmis des arguments à Select, cust.Name et cust.ID. Les propriétés d'un type anonyme créé par une requête sont toujours des propriétés de clé. Lorsque custs3 est exécuté dans la boucle For Each suivante, il en résulte une collection d'instances d'un type anonyme avec deux propriétés de clé, Name et ID.

For Each selectedCust In custs3
    Console.WriteLine(selectedCust.ID & ": " & selectedCust.Name)
Next

Les éléments de la collection représentée par custs3 sont fortement typés, et vous pouvez utiliser IntelliSense pour parcourir les propriétés disponibles et vérifier leurs types.

Pour plus d'informations, consultez Introduction à LINQ dans Visual Basic.

Choix d'utiliser ou non des types anonymes

Avant de créer un objet comme instance d'une classe anonyme, déterminez s'il s'agit de la meilleure option. Par exemple, si vous souhaitez créer un objet temporaire pour contenir les données connexes, et que vous n'avez pas besoin des autres champs et méthodes qu'une classe complète peut contenir, un type anonyme est une bonne solution. Les types anonymes sont également pratiques si vous souhaitez une sélection de propriétés différente pour chaque déclaration ou si vous souhaitez modifier l'ordre des propriétés. Toutefois, si votre projet inclut plusieurs objets possédant les mêmes propriétés, dans un ordre fixe, vous pouvez les déclarer plus facilement en utilisant un type nommé avec un constructeur de classe. Par exemple, il est plus facile de déclarer plusieurs instances d'une classe Product avec un constructeur approprié que de déclarer plusieurs instances d'un type anonyme.

' Declaring instances of a named type.
Dim firstProd1 As New Product("paperclips", 1.29)
Dim secondProd1 As New Product("desklamp", 28.99)
Dim thirdProd1 As New Product("stapler", 5.09)

' Declaring instances of an anonymous type.
Dim firstProd2 = New With {Key .Name = "paperclips", Key .Price = 1.29}
Dim secondProd2 = New With {Key .Name = "desklamp", Key .Price = 28.99}
Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = 5.09}

Un autre avantage des types nommés est que le compilateur peut intercepter une erreur de frappe accidentelle dans un nom de propriété. Dans les exemples précédents, firstProd2, secondProd2et thirdProd2 sont conçus pour être des instances du même type anonyme. Toutefois, si vous deviez déclarer par erreur thirdProd2 de l'une des façons suivantes, son type serait différent de celui de firstProd2 et secondProd2.

' Dim thirdProd2 = New With {Key .Nmae = "stapler", Key .Price = 5.09}
' Dim thirdProd2 = New With {Key .Name = "stapler", Key .Price = "5.09"}
' Dim thirdProd2 = New With {Key .Name = "stapler", .Price = 5.09}

Plus important encore, il existe des limitations sur l'utilisation de types anonymes qui ne s'appliquent pas aux instances de types nommés. firstProd2, secondProd2 et thirdProd2 sont instances du même type anonyme. Toutefois, le nom du type anonyme partagé n'est pas disponible et ne peut pas figurer à la place d'un nom de type dans votre code. Par exemple, un type anonyme ne peut pas être utilisé pour définir une signature de méthode, pour déclarer une autre variable ou un autre champ ou dans une déclaration de type. En conséquence, les types anonymes ne sont pas appropriés lorsque vous devez partager des informations entre les méthodes.

Définition du type anonyme

En réponse à la déclaration d'une instance d'un type anonyme, le compilateur crée une nouvelle définition de classe qui contient les propriétés spécifiées.

Si le type anonyme contient au moins une propriété de clé, la définition de type substitue trois membres hérités de Object : Equals, GetHashCode et ToString. Le code produit pour tester l'égalité et déterminer la valeur de code de hachage considère uniquement les propriétés de clé. Si le type anonyme ne contient pas de propriétés de clé, seul ToString est substitué. Les propriétés d'un type anonyme nommées explicitement ne peuvent pas être en conflit avec ces méthodes générées. Autrement dit, vous ne pouvez pas utiliser .Equals, .GetHashCode ou .ToString pour nommer une propriété.

Les définitions de type anonymes qui possèdent au moins une propriété de clé implémentent également l'interface System.IEquatable<T>, où T est le type du type anonyme.

Pour plus d'informations sur le code créé par le compilateur et les fonctionnalités des méthodes substituées, consultez Définition du type anonyme (Visual Basic).

Voir aussi

Tâches

Comment : déclarer une instance d'un type anonyme (Visual Basic)

Comment : déduire les types et les noms de propriétés dans des déclarations de types anonymes (Visual Basic)

Référence

Key (Visual Basic)

Concepts

Initialiseurs d'objets : types nommés et anonymes (Visual Basic)

Inférence de type local (Visual Basic)

Introduction à LINQ dans Visual Basic

Comparaison entre types nommés et types anonymes (Visual Basic)

Définition du type anonyme (Visual Basic)