IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Cloner un objet


Sujet :

VB.NET

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 118
    Par défaut Cloner un objet
    Je voudrais cloner une objet.
    je vois qu'il faut implémenter le classe de l'objet par ICloneable.
    Ensuite je crée ma fonction dans la classe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Public Function Clone() As Object Implements System.ICloneable.Clone
     
    Dim newInstance As New DataGridViewIntervention
     
    ....................
    ....................
     
    Return newInstance
     
    End Function
    Mais comment je fais pour renvoyer une référence d'une copie de l'objet et non la référence elle meme de cet objet ....

    Merci.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    et bien là tu retournes bien un nouvel objet je ne vois pas ce qui te tracasse ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 118
    Par défaut
    Oui mais si je complète le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Public Function Clone() As Object Implements System.ICloneable.Clone
     
    Dim newInstance As New DataGridViewIntervention
     
    newInstance = Me 
    'il faudrait un creatInstance ou quelque chose comme ça ??????
     
    Return newInstance
     
    End Function
    en fait la je renvoi une référence qui est la même pour les 2 objets.
    Donc je ne peux pas modifier l'objet que je renvoi sans modifier "Me".

    j'espère que j'ai été plus clair.

    En clair: Comment je fais pour cloner un objet ?

    Merci à toi

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    il faut que tu copies dans la nouvelle instance toutes les propriétés de l'instance à cloner

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 118
    Par défaut
    Cela veux dire que si j'ajoute des propriétés dans ma classe, je dois également les ajouter dans ma fonction clone ? Il n'y a pas de moyen d'éviter ça ?

    Sinon je pensais avoir trouvé une solution. J'ai créé une fonction toute simple dans mon module outil :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        Public Function clone(ByVal obj As Object) As Object
     
            Return obj
     
        End Function
    je me disais qu'en utilisant ByVal j'allais pouvoir créer une copie que je retourne ...

    Mais malheureusement cela n'a pas l'air de marcher et je ne comprend pas pourquoi ?

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    dans le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Public Function Clone() As Object Implements System.ICloneable.Clone
     
    Dim newInstance As New DataGridViewIntervention
     
    newInstance = Me 
     
    Return newInstance
     
    End Function
    le newInstance = Me il est un peu con
    par juste au dessus tu dis que newInstance est un New DataGridViewIntervention
    donc return newInstance et ca sera 2 références différentes

    par contre pour cloner un objet il ne suffit pas d'en créer un nouveau du meme type, il faut aussi parcourir toutes les propriétés pour les copier (et pour les types par références il faut choisir si on les clones ou si on utilises les meme ref)

    et puis cherche (msdn,google ou autre) les différences entre byval et byref, les types par valeurs et les types par références ... parce que là on voit que tu crois que ca marche d'une certaine manière alors que pas du tout
    peut etre revoir le mot clé new aussi
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Membre chevronné Avatar de _PascalC_
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 220
    Par défaut
    Quand tu passe une classe en ByVal tu ne fais pas une copie de l'objet entier mais seulement une copie du pointeur vers cet objet (4 ou 8 octets)

    Cela veux dire que si j'ajoute des propriétés dans ma classe, je dois également les ajouter dans ma fonction clone.
    Oui. Tu pourrais surement bricoler quelque chose à base de réflexion en parcourant les élements composant ta classe mais ça aurait un impact non négligeable sur les perf. Perso je conseillerais pas...

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 118
    Par défaut
    Ok, merci à toi Pol63, effectivement j'avais mal compris les mots cle ByRef et ByVal.

    En fait si j'ai bien compris maintenant ByVal permet de protéger les arguments. Ainsi la procédure appelé peut triturer tant qu'elle veut les arguments, la procédure appelante retrouvera toujours ses valeurs d'origine.
    Donc effectivement c'est pas exactement une copie qui est faite...

    le newInstance = Me il est un peu con
    par juste au dessus tu dis que newInstance est un New DataGridViewIntervention
    donc return newInstance et ca sera 2 références différentes
    --> c'était pour expliquer ce que je voulais faire, je voulais que ma nouvelle instance soit une copie de Me, en sachant que ce n'était pas la solution.
    Effectivement si je renvoi newIntance directement juste après avoir fait le new, je renvoi un objet DataGridViewIntervention qui à une autre référence de Me mais qui n'ai pas une copie.


    Donc effectivement, je comprends donc qu'il n'y a pas de solution simple pour copier une objet, il faut créer l'objet (en faisant un new) et affecter toutes les propriétés de l'objet d'origine à l'objet copie.


    Merci pour votre aide.

  9. #9
    Membre chevronné Avatar de _PascalC_
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2008
    Messages
    220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 220
    Par défaut
    Ainsi la procédure appelé peut triturer tant qu'elle veut les arguments, la procédure appelante retrouvera toujours ses valeurs d'origine.
    Non pas avec un type référence, comme tu travaille directement sur le même objet et non une copie. Tu passe juste le pointeur ou bien une copie du pointeur (suivant que tu es en Byval ou en byref)
    Exemple avec ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    Public Class Class1
        Public ID As Integer
        Public Name As String
     
        Public Sub New(ByVal id As Integer, ByVal name As String)
            Me.ID = id
            Me.Name = name
        End Sub
    End Class
     
    Module Module1
        Sub Main()
            Dim c As New Class1(1, "Pascal")
            Test(c)
            Console.WriteLine(c.Name) 'Affiche Toto
        End Sub
     
        Sub Test(ByVal c As Class1)
            c.Name = "Toto"
        End Sub
    End Module
    ... l'objet d'origine a bien été modifié par la méthode "test"

  10. #10
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    pour byref et byval j'ai expliqué ici la différence dans les 2 cas (type par valeur ou type par référence)
    http://www.developpez.net/forums/d50...f/#post3014623

    ensuite donc il faut en théorie après créé la nouvelle instance faire
    newInstance.tellePropriété = me.tellePropriété
    pour toutes les propriétés que tu juges intéréssant à copier

    par contre chaque propriété il faut se poser la question des référence
    pour une font par exemple qui est une structure (donc un type par valeur), si tu fais newI.font = me.font
    étant donné que c'est un type par valeur, une nouvelle font identique va etre créée pour mettre dans newI
    donc en modifiant newI.font plus tard, ca ne modifiera pas me.font en même temps
    par contre pour une propriété qui est un type par valeur (une classe) si tu fais newI.propriete = me.propriete, les 2 étant des pointeurs vers l'instance de l'objet, il vont pointer sur le même
    et alors si plus tard tu fais newI.ProprieteParRerefence.UneProprieteDeCetteClasse = tellevaleur, ca va impacter me en même temps !
    donc si ce n'est pas ce que tu veux, il faut alors cloner cette propriété aussi !

    après par reflection on doit pouvoir éviter de taper une ligne par propriété en faisant une boucle sur les propriétés pour les copier dans la nouvelle instance
    mais il faut connaitre la reflection, pas forcément compliqué une fois qu'on a compris, mais qui est un concept un peu abstrait la première fois qu'on voit que ca existe
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Pour te faciliter un peu le travail, tu peux utiliser la méthode protégée MemberwiseClone, qui effectue une "shallow copy" de l'objet (c'est à dire une copie "superficielle" : ça copie juste les propriétés de premier niveau, sans descendre dans les sous objets)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Public Function Clone() As Object Implements System.ICloneable.Clone
     
        Dim newInstance As DataGridViewIntervention
        newInstance = DirectCast(Me.MemberwiseClone(), DataGridViewIntervention)
        Return newInstance
     
    End Function

Discussions similaires

  1. Comment cloner un objet ?
    Par rei.uchiwa dans le forum Langage
    Réponses: 2
    Dernier message: 29/04/2010, 22h48
  2. Cloner un objet
    Par womannosky dans le forum Langage
    Réponses: 12
    Dernier message: 20/09/2008, 17h45
  3. [POO] cloner un objet (et tous ses sous objets ?)
    Par Merfolk dans le forum Langage
    Réponses: 11
    Dernier message: 05/05/2008, 16h23
  4. [WD9] Cloner un objet
    Par Romanops dans le forum WinDev
    Réponses: 12
    Dernier message: 06/02/2006, 15h52
  5. Cloner un objet : comment créer l'instance ?
    Par phplive dans le forum Langage
    Réponses: 8
    Dernier message: 29/05/2005, 18h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo