1873 votos

Profundo de la clonación de objetos

Quiero hacer algo como:

myObject myObj = GetmyObj(); //Create and fill a new object
myObject newObj = myObj.Clone();

Y, a continuación, hacer los cambios para el nuevo objeto que no se reflejan en el objeto original.

Yo no, a menudo necesita esta funcionalidad, así que cuando ha sido necesario, he decidido crear un nuevo objeto y, a continuación, copia de cada propiedad individual, pero siempre me deja con la sensación de que hay una forma mejor y más elegante manera de manejar la situación.

¿Cómo puedo clon o copia profunda de un objeto de modo que el objeto clonado puede ser modificada sin ningún tipo de cambios se reflejan en el objeto original?

1494voto

johnc Puntos 12140

Mientras que el estándar de la práctica es implementar la ICloneable de interfaz (que se describe aquí, así que no voy a regurgitar), he aquí una bonita profundo clon objeto de la copiadora he encontrado en El Proyecto de Código hace un tiempo y se incorporó en nuestras cosas.

Como se ha mencionado en otro lugar, se requiere que los objetos sean serializables.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep Copy of the object.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>The copied object.</returns>
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        // Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}

La idea es que se serializa el objeto y, a continuación, deserializa en un nuevo objeto. El beneficio es que usted no tiene que preocuparse acerca de la clonación de todo cuando un objeto es demasiado complejo.

Y con el uso de los métodos de extensión (también de la originalmente hace referencia a la fuente):

En caso de que prefiera utilizar los nuevos métodos de extensión de C# 3.0, cambiar el método a tener la siguiente firma:

public static T Clone<T>(this T source)
{
   //...
}

Ahora la llamada al método simplemente se convierte objectBeingCloned.Clone();.

189voto

craastad Puntos 697

Yo quería un clonador para objetos muy sencillos de la mayoría de las primitivas y las listas. Si el objeto está fuera de la caja JSON serializable, a continuación, este método va a hacer el truco. Esto no requiere ninguna modificación o implementación de interfaces en el clonado de la clase, sólo un JSON serializador como JSON.NET.

public static T Clone<T>(T source)
{
    var serialized = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(serialized);
}

151voto

Kyralessa Puntos 76456

La razón para no usar ICloneable es no porque no tiene una interfaz genérica. La razón por la que no lo uso es porque es vago. No tiene claro si va a adquirir un poco profunda o una copia profunda; es decir, hasta el implementador.

Sí, MemberwiseClone hace una copia superficial, pero lo opuesto MemberwiseClone no Clone; sería, tal vez, DeepClone, que no existe. Cuando se utiliza un objeto a través de su interfaz ICloneable, usted no puede saber qué tipo de clonación el objeto subyacente se realiza. (Y XML comentarios no dejar claro, porque vas a conseguir la interfaz de comentarios en lugar de los que están en el objeto del método Clone.)

Lo que suele hacer es simplemente hacer una Copy método que hace exactamente lo que quiero.

117voto

Ian P Puntos 7930

He aquí un buen recurso que he utilizado en el pasado: C# Objeto de Clonación

69voto

Nick Puntos 7173

Yo prefiero un constructor de copia para un clon. La intención es clara.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X