ventajas tipos terapeutica que proceso humana historia desventajas consiste clonacion .net theory cloning

tipos - ¿Por qué es tan difícil la clonación(en.NET)?



tipos de clonacion (5)

En el pasado tuve la necesidad de clonar objetos, solo para encontrar que no implementan un método Clone() , lo que me obliga a hacerlo a mano (crear una nueva instancia y copiar todas las propiedades del original al nuevo)

¿Por qué la clonación no es tan fácil como duplicar el bloque de memoria en el que se asigna el objeto y, por lo tanto, tener el método de Clone en la clase de object , y todas las clases en .NET lo heredan?


Existe tal cosa como Object.MemberwiseClone() que hace lo que usted describe. Está haciendo una copia superficial del objeto.

No hará una clonación automática automáticamente ... tendrá que llamar a clonar en todos los objetos miembros manualmente, etc.


Hay (al menos) dos tipos de clonación. La mayoría de las referencias hablan de clonación superficial y profunda , pero en realidad hay matices intermedios.

El problema clave es la tensión entre "cuánto se debe copiar" y "cuánto se debe compartir".

Considere un objeto de Order , que contenga referencias a un Customer , una Address y una List de OrderLines de OrderLines .

Si quieres Clone() una Order , ¿qué implica?

" Solo copiando el bloque de memoria " le daría un nuevo Order , pero uno que compartiera el Customer , la Address y la misma List de OrderLines de OrderLines . (Recuerde que los miembros del objeto se almacenan por referencia, de modo que cuando duplica el bloque de memoria, obtiene dos referencias al mismo objeto).

Claramente, no desea compartir la List de OrderLines Order entre las dos Order . De hecho, es probable que también desee clonar cada OrderLine .

Si estuviera trabajando con un método Clone() propósito general, ¿cómo sabría ese método qué miembros deberían clonarse de forma recursiva y cuáles no?

En general, este es un problema intratable, por lo que depende de los objetos individuales implementar la semántica adecuada para su situación .

Una nota final: incluso cuando creo la capacidad de Clone() objetos Clone() , no tiendo a crear un método Clone() , sino que prefiero un constructor de copia , un constructor que acepta otro objeto como base. Si no puedes encontrar Clone() , busca eso.


Otros ya han explicado sobre MemberwiseClone , pero nadie dio la explicación de por qué está protegido. Voy a tratar de dar la razón de ser.

El problema aquí es que MemberwiseClone simplemente copia ciegamente el estado. En muchos casos, esto es indeseable. Por ejemplo, el objeto puede tener un campo privado que es una referencia a una List . Una copia superficial, como lo que hace MemberwiseClone , daría lugar a que un nuevo objeto apunte a la misma lista, y la clase puede escribirse sin esperar que la lista se comparta con nadie más.

O un objeto puede tener algún tipo de campo de ID, generado en el constructor. De nuevo, cuando clonas eso, obtienes dos objetos con la misma ID, lo que puede llevar a todo tipo de fallas extrañas en los métodos que suponen que la ID es única.

O diga que tiene un objeto que abre un socket o una secuencia de archivos y almacena una referencia a eso. MemberwiseClone simplemente copiará la referencia, y puede imaginar que dos objetos que intentan intercalar llamadas en el mismo flujo no terminarán bien.

En resumen, la "clonación" no es una operación bien definida para objetos arbitrarios. El hecho de que memberwise operator= se proporciona para todas las clases de forma predeterminada en C ++ es más una molestia, ya que con demasiada frecuencia la gente olvida que está ahí, y no la deshabilita para las clases en las que copiar no tiene sentido, o es peligroso (y hay sorprendentemente muchas clases de este tipo).


Porque eso no realizaría un clon profundo, que generalmente es lo que los clones realmente necesitan ser. Imagine que tiene una referencia a una matriz, o una lista ... simplemente copiando la memoria tomada por su objeto simplemente clonará la referencia. Cualquier cambio en la matriz será visible a través del clon así como también del objeto original, por lo que los dos objetos aún están conectados, lo que viola el punto normal de clonación.

Si desea implementar exactamente esa funcionalidad, es fácil: para eso Object.MemberwiseClone() . La mayoría de las veces, si incluso tiene sentido clonar un objeto (¿qué significa un NetworkStream clonado?) Tiene sentido clonar cada propiedad ... a menos que se refiera a un valor inmutable, etc. En otras palabras, esto es un problema naturalmente difícil, por lo que la mayoría de los tipos no admiten la clonación.

Si se adhiere a tipos inmutables siempre que sea posible, no es tanto un problema ... eso dificulta otras cosas, es cierto, pero puede ser muy poderoso en muchos casos.


Tienes que implementar explícitamente la interfaz ICloneable en tus clases.

Sin embargo, como indica la documentación, el mecanismo de clonación en Object.MemberwiseClone() no distingue entre copia superficial y profunda.