Crear una copia de un objeto en C #[duplicar]


Posible Duplicado:
¿Cómo se hace una copia profunda de un objeto en. Net (específicamente en C#)?

Por favor, eche un vistazo al siguiente código (extracto de un libro de C#):

namespace Example {
    class MyClass {
        public int val;
    }

    struct myStruct {
        public int val;
    }

    class Program {
        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();
        }
    }
}

Entiendo que produce la salida siguiente

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

Las dos últimas líneas de la salida no tengo ningún problema, pero las dos primeras me dicen que objectA y objectB están apuntando al mismo bloque de memoria (ya que en C#, los objetos son tipos de referencia).

El la pregunta es cómo hacer objectB, una copia de objectA para que apunte a un área diferente en la memoria. Entiendo que tratar de asignar a sus miembros puede no funcionar, ya que esos miembros también pueden ser referencias. Entonces, ¿cómo hago para hacer objectB una entidad completamente diferente de objectA?

Gracias

Author: Margaret, 2011-07-04

4 answers

No hay una forma incorporada. Puede hacer que MyClass implemente la interfaz IClonable (pero está en desuso) o simplemente escriba su propio método de Copia/clonación. En cualquier caso tendrás que escribir algún código.

Para objetos grandes podría considerar Serialización + Deserialización (a través de un MemoryStream), solo para reutilizar el código existente.

Sea cual sea el método, piense cuidadosamente qué significa exactamente "una copia". Qué tan profundo debe ir, hay campos de Id a exceptuar, etc.

 87
Author: Henk Holterman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-25 07:54:13

Usted podría hacer:

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

Entonces puedes hacer

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

N. B. MemberwiseClone() Crea una copia superficial del Sistema actual.Objeto.

 112
Author: BugFinder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-24 16:06:50

La forma más fácil de hacer esto es escribir un constructor de copia en la clase MyClass.

Algo como esto:

namespace Example
{
    class MyClass
    {
        public int val;

        public MyClass()
        {
        }

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

El segundo constructor simplemente acepta un parámetro de su propio tipo (el que desea copiar) y crea un nuevo objeto asignado con el mismo valor

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();
    }
}

Salida:

objectA.val = 10

objectB.val = 20               
 39
Author: Levi_vc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-29 18:08:37

Ya hay una pregunta sobre esto, tal vez podría leerla

Clonación profunda de objetos

No hay un método Clone() como existe en Java, por ejemplo, pero podrías incluir un constructor de copia en tus clases, ese es otro buen enfoque.

class A
{
  private int attr

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

  public A()
  {
  }

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

Este sería un ejemplo, copiando el miembro 'Attr' al construir el nuevo objeto.

 8
Author: jgemedina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:36