Leer en inglés

Compartir a través de


Object.MemberwiseClone Método

Definición

Crea una copia superficial del Objectactual.

C#
protected object MemberwiseClone();

Devoluciones

Copia superficial del Objectactual.

Ejemplos

En el ejemplo siguiente se muestra el método MemberwiseClone. Define un método ShallowCopy que llama al método MemberwiseClone para realizar una operación de copia superficial en un objeto Person. También define un método DeepCopy que realiza una operación de copia profunda en un objeto Person.

C#
using System;

public class IdInfo
{
    public int IdNumber;

    public IdInfo(int IdNumber)
    {
        this.IdNumber = IdNumber;
    }
}

public class Person
{
    public int Age;
    public string Name;
    public IdInfo IdInfo;

    public Person ShallowCopy()
    {
        return (Person)MemberwiseClone();
    }

    public Person DeepCopy()
    {
        Person other = (Person)MemberwiseClone();
        other.IdInfo = new IdInfo(IdInfo.IdNumber);
        return other;
    }
}

public class Example
{
    public static void Main()
    {
        // Create an instance of Person and assign values to its fields.
        Person p1 = new()
        {
            Age = 42,
            Name = "Sam",
            IdInfo = new IdInfo(6565)
        };

        // Perform a shallow copy of p1 and assign it to p2.
        Person p2 = p1.ShallowCopy();

        // Display values of p1, p2
        Console.WriteLine("Original values of p1 and p2:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(p2);

        // Change the value of p1 properties and display the values of p1 and p2.
        p1.Age = 32;
        p1.Name = "Frank";
        p1.IdInfo.IdNumber = 7878;
        Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(p2);

        // Make a deep copy of p1 and assign it to p3.
        Person p3 = p1.DeepCopy();
        // Change the members of the p1 class to new values to show the deep copy.
        p1.Age = 39;
        p1.Name = "George";
        p1.IdInfo.IdNumber = 8641;
        Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p3 instance values:");
        DisplayValues(p3);
    }

    public static void DisplayValues(Person p)
    {
        Console.WriteLine($"      Name: {p.Name:s}, Age: {p.Age:d}");
        Console.WriteLine($"      Value: {p.IdInfo.IdNumber:d}");
    }
}

/* The example displays the following output:
 * 
 * Original values of p1 and p2:
      p1 instance values:
         Name: Sam, Age: 42
         Value: 6565
      p2 instance values:
         Name: Sam, Age: 42
         Value: 6565

   Values of p1 and p2 after changes to p1:
      p1 instance values:
         Name: Frank, Age: 32
         Value: 7878
      p2 instance values:
         Name: Sam, Age: 42
         Value: 7878

   Values of p1 and p3 after changes to p1:
      p1 instance values:
         Name: George, Age: 39
         Value: 8641
      p3 instance values:
         Name: Frank, Age: 32
         Value: 7878
 */

En este ejemplo, la propiedad Person.IdInfo devuelve un objeto IdInfo. Como se muestra en la salida del ejemplo, cuando se clona un objeto Person llamando al método MemberwiseClone, el objeto Person clonado es una copia independiente del objeto original, salvo que comparten la misma referencia de objeto Person.IdInfo. Como resultado, modificar la propiedad Person.IdInfo del clon cambia la propiedad Person.IdInfo del objeto original. Por otro lado, cuando se realiza una operación de copia profunda, el objeto clonado Person, incluida su propiedad Person.IdInfo, se puede modificar sin afectar al objeto original.

Comentarios

El método MemberwiseClone crea una copia superficial mediante la creación de un nuevo objeto y, a continuación, copia los campos no estáticos del objeto actual en el nuevo objeto. Si un campo es un tipo de valor, se realiza una copia bit a bit del campo. Si un campo es un tipo de referencia, la referencia se copia, pero el objeto al que se hace referencia no es; por lo tanto, el objeto original y su clon hacen referencia al mismo objeto.

Para ilustrar la diferencia entre una operación de copia superficial y profunda, considere un objeto denominado X que hace referencia a los objetos A y B. Objeto B, a su vez, hace referencia al objeto C. Una copia superficial de X crea un nuevo objeto X2 que también hace referencia a los objetos A y B. Por el contrario, una copia profunda de X crea un nuevo objeto X2 que hace referencia a los nuevos objetos A2 y B2, que son copias de A y B2, a su vez, hace referencia al nuevo objeto C2, que es una copia de C.

Hay numerosas maneras de implementar una operación de copia profunda si la operación de copia superficial realizada por el método MemberwiseClone no satisface sus necesidades. Estos incluyen lo siguiente:

  • Llame a un constructor de clase del objeto que se va a copiar para crear un segundo objeto con valores de propiedad tomados del primer objeto. Esto supone que los valores de un objeto están definidos por completo por su constructor de clases.
  • Llame al método MemberwiseClone para crear una copia superficial de un objeto y, a continuación, asigne nuevos objetos cuyos valores sean los mismos que el objeto original a las propiedades o campos cuyos valores son tipos de referencia. El método DeepCopy del ejemplo ilustra este enfoque.
  • Serialice el objeto que se va a copiar en profundidad y, a continuación, restaure los datos serializados en una variable de objeto diferente.
  • Use la reflexión con recursividad para realizar la operación de copia profunda.

Se aplica a

Producto Versiones
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0