Pregunta

Tengo 2 objetos del mismo tipo y me gustaría realizar una copia superficial de un estado al otro.En C++ tengo memcpy, lo cual es genial.¿Cómo puedo hacerlo en C#?MemberwiseClone() no es lo suficientemente bueno porque crea y devuelve un nuevo objeto y me gusta copiarlo a un objeto existente.Pensé en usar la reflexión pero me temo que será demasiado lenta para el código de producción.También pensé en usar uno de los serializadores .Net, pero creo que también crean objetos en lugar de configurar uno existente.

Mi caso de uso:

Tengo un objeto de plantilla (clase, no estructura) que necesita ser actualizado por una de sus instancias (objetos hechos de esta plantilla)

¿Algunas ideas?

¿Fue útil?

Solución

[editar] con respecto a su aclaración:Según tengo entendido, tiene N objetos, cada uno tiene una referencia (directa) al objeto de plantilla.Desea volver a escribir en la plantilla para que todos los objetos "vean" estos cambios.

Sugerencia:Implementar un intermediario de plantilla.

class TemplateProvider
{
   public MyData Template { get; set; }
}

En lugar de pasar la plantilla, pase el proveedor de la plantilla a los objetos.

Para simplificar la sintaxis en los componentes, puede agregar una propiedad (¿privada/interna?)

MyData Template { get { return m_templateProvider.Template; } }
void UpdateTemplate() { m_templateProvider.Template = 
                            (MyData) this.MemberwiseClone(); }

El proveedor de plantillas también simplifica el bloqueo en escenarios multiproceso.


En resumen, de ninguna manera a menos que lo hagas tú mismo.Pero, ¿por qué no crear un nuevo objeto si anula todas las propiedades de todos modos?

memcopy y construcciones similares de bajo nivel no son apoyadas porque socavan las garantías otorgadas por el medio ambiente.

Se realiza una copia superficial de las estructuras mediante asignación.Para clases, MemberwiseClone es el método para hacerlo, pero como usted dice, eso crea un nuevo objeto.

No existe una forma integrada para esto y, como potencialmente rompe la encapsulación, debe usarse con cuidado de todos modos.

Podrías crear una rutina genérica usando la reflexión, pero si funciona o no depende de la clase misma.Y sí, será comparativamente lento.

Lo que queda es respaldarlo mediante una interfaz personalizada.Puede proporcionar una rutina genérica de "Copia superficial" que verifique la interfaz y la use, y recurra a la reflexión cuando no lo haga.Esto hace que la funcionalidad esté disponible de forma general y puede optimizar las clases para las que el rendimiento importa más adelante.

Otros consejos

En C# (y en C++ también), no hay ninguna diferencia entre "nuevo objeto" y "una copia del objeto existente" siempre que todos sus miembros iguales entre sí.

Teniendo en cuenta:

Int32 a = 5;

, ambas operaciones:

Int32 b = 5;
Int32 b = a;

producir el mismo resultado.

Como se indica en MSDN referencia :

  

El método MemberwiseClone crea una copia superficial mediante la creación de un nuevo objeto y, a continuación, copiar los campos no estáticos del objeto actual al 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 a que se refiere no es; por lo tanto, el objeto original y su clon se refieren al mismo objeto.

, es decir, hace exactamente lo mismo que memcpy() en <=>

supongo que sólo podría hacer algo como:

YourObjectType A = new YourObjectType();
YourObjectType B = a.MemberwiseClone();

Esto creará un nuevo objeto en el interior del método MemberwiseClone un hacer que el objeto B referencia a él. Supongo que sirve a sus propósitos.

La asignación de una estructura a otra, para todos los efectos, funciona exactamente como memcpy en C++ en objetos POD.

Si cree que esto no se aplica a su situación, puedo asegurarle que su código C++ no cumplía con los estándares (es decir, contenía errores en forma de comportamiento indefinido).Por favor especifica (en la pregunta) qué efecto quieres lograr.Esto será más útil que hablar sobre replicar un comportamiento indefinido en otro idioma.

namespace WindowsFormsApplication7
{

    [Serializable] // just put this in your class
    class Mate
    {
        public string SomeProperty { get; set; }
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();


            var mA = new Mate();
            mA.SomeProperty = "Hey";

            var vf = new BinaryFormatter();
            var ns = new MemoryStream();
            vf.Serialize(ns, mA);
            byte[] vytes = ns.ToArray();


            var vfx = new BinaryFormatter();
            var nsx = new MemoryStream();            
            nsx.Write(vytes, 0, vytes.Length);
            nsx.Seek(0, 0);
            var mB = (Mate)vfx.Deserialize(nsx);

            mA.SomeProperty = "Yo";

            MessageBox.Show(mA.SomeProperty); // Yo
            MessageBox.Show(mB.SomeProperty); // Hey
        }
    }
}
namespace WindowsFormsApplication7
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var dt = new DataTable();
            dt.Columns.Add("lastname", typeof(string));
            dt.Columns.Add("firstname", typeof(string));

            dt.Rows.Add("lennon", "john");
            dt.Rows.Add("mccartney", "paul");


            var ms = new MemoryStream();
            var bf = new BinaryFormatter();
            bf.Serialize(ms, dt);
            byte[] bytes = ms.ToArray();



            var bfx = new BinaryFormatter();
            var msx = new MemoryStream();
            msx.Write(bytes, 0, bytes.Length);
            msx.Seek(0, 0);


            // doesn't just copy reference, copy all contents
            var dtx = (DataTable)bfx.Deserialize(msx);


            dtx.Rows[0]["lastname"] = "Ono";


            // just copy reference
            var dty = dt;

            dty.Rows[0]["lastname"] = "Winston";

            MessageBox.Show(dt.Rows[0]["lastname"].ToString()); // Winston
            MessageBox.Show(dtx.Rows[0]["lastname"].ToString()); // Ono
            MessageBox.Show(dty.Rows[0]["lastname"].ToString()); // Winston

        }
    }
}

No puedo utilizar un objeto recién creado porque me gusta el plantilla objeto a ser cambiado de acuerdo con el estado de uno de sus casos (es decir, ejemplo hecho de que la plantilla)

Cuando lo pienso, es muy interesante mirar el código de implementación del método MemberWiseClone() y ver cómo Microsoft resolvió mi pregunta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top