ProgrammationDéveloppeur VB.NET

Comment réaliser la copie d'objets en Visual Basic : différence entre la copie superficielle (shallow) et la copie profonde (deep), et comment copier correctement des objets avec des types de référence imbriqués ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

En Visual Basic, il est souvent nécessaire de créer une copie d'un objet pour modifier les données d'une manière nouvelle sans affecter la structure d'origine. Il est essentiel de différencier la copie superficielle (shallow) et la copie profonde (deep), surtout si les objets contiennent des types de référence imbriqués.

Contexte de la question :
La copie superficielle ne copie que les valeurs des propriétés primitives et des références aux objets imbriqués, tandis que la copie profonde crée de nouvelles instances de tous les objets imbriqués. La distinction est fondamentale lors du travail avec des données complexes, par exemple si un objet contient des collections ou d'autres objets.

Problème :
Si vous copiez un objet par référence ou utilisez la méthode standard MemberwiseClone, alors lors de la modification des objets imbriqués, la structure d'origine changera en même temps que la copie — cela est dangereux pour la logique métier et peut entraîner des bugs difficiles à détecter.

Solution :
En VB.NET, il n'existe pas de méthode automatique pour la copie profonde, donc elle doit être réalisée manuellement ou via la sérialisation. Onimplémente généralement une méthode personnalisée DeepCopy en créant de nouvelles instances de tous les objets imbriqués.

Exemple de code pour la copie superficielle et profonde :

Class Person Public Name As String Public Address As Address ' Copie superficielle Public Function ShallowCopy() As Person Return CType(Me.MemberwiseClone(), Person) End Function ' Copie profonde Public Function DeepCopy() As Person Dim copy As Person = CType(Me.MemberwiseClone(), Person) copy.Address = New Address() With {.City = Me.Address.City} Return copy End Function End Class Class Address Public City As String End Class

Caractéristiques clés :

  • La copie superficielle ne crée pas de nouveaux objets pour les champs de référence.
  • La copie profonde nécessite une copie manuelle ou une sérialisation.
  • Les erreurs sont souvent dues à l'ignorance de l'endroit où une copie profonde est nécessaire et où une copie superficielle l'est.

Questions pièges.

Que retourne l'opérateur = lors de la copie d'un objet de classe en Visual Basic ?

Réponse : L'opérateur = pour les types de référence attribue une référence et ne copie pas les valeurs. Par conséquent, les deux variables pointeront vers le même objet.

Dim a As New Person() Dim b As Person = a ' Maintenant a et b sont des références vers le même objet

Peut-on utiliser MemberwiseClone pour une copie profonde ?

Réponse : Non. La méthode MemberwiseClone implémente uniquement la copie superficielle — tous les types de référence imbriqués sont copiés par référence.

Pourquoi la sérialisation n'est-elle pas toujours un moyen universel de copie profonde ?

Réponse : La sérialisation fonctionne uniquement avec des objets sérialisables et peut ne pas prendre en charge les propriétés de type Object ou celles non marquées comme Serializable. De plus, la sérialisation est souvent plus lente que la copie standard.

Erreurs typiques et anti-patterns

  • Utilisation de l'opérateur = pour copier des objets complexes.
  • Utilisation de MemberwiseClone pour une copie profonde.
  • Ignorance de la structure de l'objet lors de l'écriture de la méthode DeepCopy.

Exemple de la vie réelle

Cas négatif

Le client copie un objet de commande avec l'opérateur = pour passer une nouvelle commande, sans réaliser que la liste imbriquée des articles reste la même pour deux objets.

Avantages : Rapide, simple

Inconvénients : Les changements dans une commande affectent l'autre — erreurs critiques dans la gestion des stocks.

Cas positif

Une méthode DeepCopy est implémentée pour copier la commande avec tous les produits imbriqués et l'adresse de livraison.

Avantages : Séparation fiable des données, logique métier correcte

Inconvénients : Nécessite une attention particulière à la structure de l'objet, plus de code à maintenir