web-dev-qa-db-fra.com

Créer une copie d'un objet en C #

Duplicate possible:
Comment faire une copie profonde d'un objet en .Net (C # en particulier)?

Veuillez consulter le code ci-dessous (extrait d'un livre C #):

public class MyClass 
{
    public int val;
}
public struct myStruct 
{
    public int val;
}
public class Program 
{
    private static void Main(string[] args) 
    {
        MyClass objectA = new MyClass();
        MyClass objectB = objectA;

        objectA.val = 10;
        objectB.val = 20;

        myStruct structA = new myStruct();
        myStruct structB = structA;

        structA.val = 30;
        structB.val = 40;

        Console.WriteLine("objectA.val = {0}", objectA.val);
        Console.WriteLine("objectB.val = {0}", objectB.val);
        Console.WriteLine("structA.val = {0}", structA.val);
        Console.WriteLine("structB.val = {0}", structB.val);

        Console.ReadKey();
    }
}

Je comprends que cela produit le résultat ci-dessous:

objectA.val = 20
objectB.val = 20
structA.val = 30
structB.val = 40

Les deux dernières lignes de la sortie ne me posent pas de problème, mais les deux premières me disent que objectA et objectB pointent vers le même bloc de mémoire (car en C #, les objets sont des types de référence).

La question est de savoir comment créer objectB, une copie de objectA de sorte qu’elle pointe vers une zone différente de la mémoire. Je comprends qu’essayer d’affecter leurs membres peut ne pas marcher puisque ces membres peuvent aussi être des références. Alors, comment puis-je créer objectB une entité complètement différente de objectA?

Merci

144
afaolek

Il n'y a pas de manière intégrée. Vous pouvez demander à MyClass d'implémenter l'interface IClonable (mais c'est en quelque sorte déconseillé) ou tout simplement d'écrire votre propre méthode Copy/Clone. Dans les deux cas, vous devrez écrire du code.

Pour les gros objets, vous pouvez envisager la sérialisation et la désérialisation (via un MemoryStream), juste pour réutiliser le code existant.

Quelle que soit la méthode, réfléchissez bien à ce que "copie" signifie exactement. À quelle profondeur doit-il aller, y a-t-il des champs Id à exclure, etc.

102
Henk Holterman

Vous pourriez faire:

class myClass : ICloneable
{
    public String test;
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

alors vous pouvez faire

myClass a = new myClass();
myClass b = (myClass)a.Clone();

N.B. MemberwiseClone() Crée une copie superficielle du System.Object actuel.

126
BugFinder

Le moyen le plus simple consiste à écrire un constructeur de copie dans la classe MyClass.

Quelque chose comme ça:

namespace Example
{
    class MyClass
    {
        public int val;

        public MyClass()
        {
        }

        public MyClass(MyClass other)
        {
            val = other.val;
        }
    }
}

Le second constructeur accepte simplement un paramètre de son propre type (celui que vous voulez copier) et crée un nouvel objet assigné avec la même valeur

class Program
{
    static void Main(string[] args)
    {
        MyClass objectA = new MyClass();
        MyClass objectB = new MyClass(objectA);
        objectA.val = 10;
        objectB.val = 20;
        Console.WriteLine("objectA.val = {0}", objectA.val);
        Console.WriteLine("objectB.val = {0}", objectB.val);
        Console.ReadKey();
    }
}

sortie:

objectA.val = 10

objectB.val = 20               
45
Levi_vc

Il y a déjà une question à ce sujet, vous pourriez peut-être la lire

objets de clonage profond

Il n'y a pas de méthode Clone () telle qu'elle existe dans Java par exemple, mais vous pouvez inclure un constructeur de copie dans vos classements, c'est une autre bonne approche.

class A
{
  private int attr

  public int Attr
  {
     get { return attr; }
     set { attr = value }
  }

  public A()
  {
  }

  public A(A p)
  {
     this.attr = p.Attr;
  }  
}

Ce serait un exemple, en copiant le membre 'Attr' lors de la construction du nouvel objet.

9
jgemedina