c# serialization copying

C#memcpy equivalente



serialization copying (8)

Tengo 2 objetos del mismo tipo y me gustaría copiar poco a poco un estado al otro. En C ++ tengo memcpy, que es genial. ¿Cómo puedo hacerlo en C #? El MemberwiseClone () no es lo suficientemente bueno porque crea y devuelve un nuevo objeto y me gusta copiar a un objeto existente. Pensé en usar la reflexión, pero me temo que será demasiado lento 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 establecer uno existente.

Mi caso de uso:

Tengo un objeto de plantilla (class not struct) que necesita ser actualizado por una de sus instancias (objetos hechos de esta plantilla)

¿Algunas ideas?


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


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

Dado:

Int32 a = 5;

, ambas operaciones:

Int32 b = 5; Int32 b = a;

produce el mismo resultado.

Como se indica en la referencia de MSDN :

El método MemberwiseClone crea una copia superficial creando un nuevo objeto y luego copiando los campos no estáticos del objeto actual al nuevo objeto.

Si un campo es un tipo de valor, se realiza una copia bit por bit del campo.

Si un campo es un tipo de referencia, la referencia se copia pero el objeto referido no; por lo tanto, el objeto original y su clon se refieren al mismo objeto.

, es decir, hace exactamente lo mismo que memcpy() en C++


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

Si sientes que esto no se aplica a tu situación, entonces puedo asegurarte que tu código C ++ no se ajustaba al estándar (es decir, contenía errores en forma de comportamiento indefinido). Por favor especifique ( en la pregunta ) qué efecto desea lograr. Esto será más útil que hablar de replicar un comportamiento indefinido en otro idioma.


No puedo usar un objeto recién creado porque me gusta que el objeto de la plantilla se modifique de acuerdo con el estado de una de sus instancias (es decir, instancia hecha de esa plantilla)


Supongo que podrías hacer algo como:

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

Esto creará un nuevo objeto dentro del método MemberwiseClone y hará que el objeto B lo haga referencia. Supongo que sirve a tus propósitos.


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 } } }


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

Sugerencia: imponer un intermediario de plantillas.

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 plantilla 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 de bajo nivel similares no son compatibles ya que socavan las garantías hechas por el medio ambiente.

Una copia superficial para las estructuras se hace por asignación. Para las clases, MemberwiseClone es el método para hacerlo, pero como dices eso crea un nuevo objeto.

No hay un camino integrado para eso, y como potencialmente rompe la encapsulación, debe usarse con cuidado de todos modos.

Puede construir una rutina genérica utilizando la reflexión, pero si funciona o no depende de la clase en sí. Y sí, ti será comparativamente lento.

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