tutorial oriented concepts .net oop

.net - oriented - oop c#



¿Debería proporcionar una copia profunda al implementar ICloneable? (3)

Los clones son profundos por defecto, eso es la convención de nomenclatura y los constructores de copia pueden ser superficiales si así lo desean, por razones de rendimiento.

Editar: Esta convención de nomenclatura va más allá de las fronteras, es lo mismo para .Net, Java, C ++, Javascript, etc. ... la fuente real está más allá de mi conocimiento, pero es parte del léxico estándar orientado a objetos, al igual que los objetos y las clases. Por lo tanto, MSDN no especifica la implementación porque está dada por la palabra misma (por supuesto, muchos recién llegados a los lenguajes OO no lo saben, y DEBEN especificarlo, pero de todos modos su documentación es bastante frugal)

No me queda claro, a partir de la documentación de MSDN, si debería proporcionar un clon profundo o poco profundo al implementar ICloneable. ¿Cuál es la opción preferida?


Respuesta corta: Sí.

Respuesta larga: No use ICloneable. Eso es porque .Clone no se define como un clon superficial o profundo. Debe implementar su propia interfaz IClone y describir cómo debería funcionar el clon.


Dada la forma en que se define un objeto, no debería haber ninguna pregunta sobre "clonación profunda" versus "clonación superficial". Si un objeto encapsula las identidades de las cosas, un clon del objeto debe encapsular las identidades de las mismas cosas. Si un objeto encapsula los valores de los objetos mutables, una copia debe encapsular los objetos mutables separados con los mismos valores.

Desafortunadamente, ni .NET ni Java incluyen en el sistema de tipos si las referencias se mantienen para encapsular identidad, valor mutable, ambos, o ninguno. En su lugar, solo usan un único tipo de referencia y calculan que el código que posee la única copia de una referencia, o posee la única referencia a un contenedor que contiene la única copia de esa referencia, puede usar esa referencia para encapsular el valor o el estado. Tal pensamiento puede ser tolerable para objetos individuales, pero plantea problemas reales cuando se trata de operaciones de copiado y prueba de igualdad.

Si una clase tiene un campo Foo que encapsula el estado de una List<Bar> que debe encapsular las identidades de los objetos en él, y puede en el futuro encapsular las identidades de diferentes objetos, entonces un clon del Foo debe contener una referencia a un nuevo lista que identifica los mismos objetos. Si List<Bar> se utiliza para encapsular los estados mutables de los objetos, entonces un clon debería tener una referencia a una nueva lista que identifica nuevos objetos que tienen el mismo estado.

Si los objetos incluían métodos "equivalentes" y "equivalentes" separados, con códigos hash para cada uno, y si para cada tipo de objeto de montón había tipos de referencia que se denotaban como encapsulando identidad, estado mutable, ambos o ninguno, entonces el 99% de prueba de igualdad y los métodos de clonación podrían manejarse automáticamente. Dos agregados son iguales si todos los componentes que encapsulan la identidad o el estado mutable son equivalentes (no meramente iguales) y los que no encapsulan ninguno son al menos iguales; dos agregados son equivalentes solo si todos los componentes correspondientes son y siempre serán equivalentes [esto a menudo implica igualdad de referencia, pero no siempre]. Copiar una agregación requiere hacer una copia separada de cada constituyente que encapsula el estado mutable, copiando la referencia a cada constituyente que encapsula la identidad, y haciendo cualquiera de las anteriores para aquellas que no encapsulan ninguna de las dos; una agregación con un constituyente que encapsula tanto el estado mutable como la identidad no pueden ser clonados simplemente.

Hay algunos casos complicados que dichas reglas para la clonación, la igualdad y la equivalencia no se manejarían correctamente, pero si hubiera una convención para distinguir una List<IdentityOfFoo> de una List<MutableStateOfFoo> , y para admitir tanto "equivalentes" como "equivale a" pruebas, el 99% de los objetos pueden tener Clone, Equals, Equivalent, EqualityHash y EquivalenceHash autogenerados y funcionan correctamente.