Clonage d’objet en .NET (C# ou VB)

23 11 2011

Si vous débarquez en .NET (ou en Java d’ailleurs) et que vous venez d’un bon langage pas casse couille comme PHP ou JavaScript, ça doit vous faire un choc :

Donner un type à ses variables, choisir parmi 36000 structures pour stocker l’information (Array, List, Hasttable, Dictionary, DataTable…), devoir importer des tonnes de trucs pour simplement trier un tableau par ordre décroissant…

Mais le pire, c’est sans doute le passage par référence. En PHP, pour dupliquer une variable (qu’elle soit un simple entier ou un objet très élaboré issu d’une classe que vous avez créé), il suffit d’utiliser = comme pour n’importe quelle affectation :

<?php
$variable_originale = new MaClasse();
$variable_originale->nom = "Variable originale";
$copie = $variable_originale;
$copie->nom = 'Une copie conforme et parfaitement disctince de $variable_originale';

echo $variable_originale->nom; // Variable originale
echo $copie->nom; // Une copie conforme et parfaitement disctince de $variable_originale
?>

Mais en .NET, tout est passé par référence (sauf les types primitifs comme integer, boolean, string… qui eux sont passé par valeur), ça signifie que si vous faites la même chose qu’en PHP ci-dessus, quand vous allez modifier la variable copie, ça va aussi modifie variable_originale. Pourquoi ? Tout simplement parce que copie et variable_originale sont des pointeurs vers la même variable en mémoire, c’est en quelque sorte 2 noms différents pour la même variable.

La solution, pour dupliquer une variable, c’est de créer copie (en appelant le constructeur de MaClasse : copie = new MaClasse()), mais il faut alors recopier un par un la valeur de chaque attribut de variable_originale dans l’attribut de copie homonyme, l’enfer. En général on fait cela en créant une méthode Clone() dans la classe de la variable qu’on veut dupliquer, et en implémentant une interface de clonage comme ICloneable en .NET. C’est au développeur d’implémenter la fonction Clone().

Heureusement, il existe une solution toute bête pour créer une fonction Clone facilement : elle consiste à sérialiser la variable à dupliquer, puis à la desérialiser (ce qui reviendrait à faire un $copie = unserialize(serialize($variable_originale)); en PHP).

Voici donc une fonction permettant de cloner un objet en VB.NET (mais ça marche aussi en C#, il suffit d’adapter la syntaxe) :

Namespace Espace
    <Serializable()> Friend Class AgriVar

        Friend Sub New()
            '[...]
        End Sub

        Public Function Clone()
            Dim memStream As MemoryStream = New MemoryStream()
            Dim bnFormat As BinaryFormatter = New BinaryFormatter(Nothing, New StreamingContext(StreamingContextStates.Clone))
            bnFormat.Serialize(memSteam, Me)
            memStream.Seek(0, SeekOrigin.Begin)
            Return bnFormat.Deserialize(memStream)
        End Function

    End Class
End Namespace

Notez que j’ai écrit <Serializable()> juste devant le nom de ma classe, ne me demandez pas pourquoi, sans ça ça ne marche pas, il se produit une erreur “Le type XXX n’est pas marqué comme sérialisable”.


Partager :

Ces icônes sont des liens vers des sites de partage de signet sociaux où les lecteurs peuvent partager et découvrir de nouveaux liens.
  • Digg
  • del.icio.us
  • Facebook
  • Digg -fr
  • Live
  • MisterWong Fr
  • Scoopeo
  • StumbleUpon
  • Technorati
  • Wikio FR

Actions

Informations

Et maintenant je fais quoi ?

Laisser un commentaire

Vous pouvez utiliser ces balises html : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>