2009-03-30 19 views
106

¿Puede explicarme por qué debería heredar de ICloneable e implementar el método Clone()?¿Por qué debería implementar ICloneable en C#?

Si quiero hacer una copia profunda, ¿no puedo simplemente implementar mi método? Digamos MyClone()?

¿Por qué debería heredar de ICloneable? ¿Cuáles son las ventajas? ¿Es solo cuestión de hacer que el código sea "más legible"?

+0

** Vea también **: [La controversia de ICloneable: ¿Debe una clase implementar ICloneable o no?] (Http://www.sysexpand.com/?path=howto/implement-icloneable-or-not) – KyleMit

Respuesta

111

No deberías. Microsoft recomienda no implementar ICloneable porque no hay una indicación clara de la interfaz si su método Clone realiza un clon "profundo" o "superficial".

Consulte this blog post from Brad Abrams en 2003 (!) Para obtener más información.

+4

Wayback enlace al artículo, que ahora es 404: http://web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/archive/2003/04/09/49935.aspx – harpo

+1

Un enlace mejor : https://blogs.msdn.microsoft.com/brada/2004/05/03/should-we-obsolete-icloneable-the-slar-on-system-icloneable/ –

18

ICloneable es uno de esos artefactos en el BCL que ha sido controvertido. No hay una razón real en mi humilde opinión para implementarlo. Dicho esto, si voy a crear un método de clonación, entonces implementaré ICloneable, y proporciono mi propia versión fuerte de Clone.

El problema con ICloneable es que nunca se indicó si Clone era una copia superficial o una copia profunda que son cosas muy diferentes. El hecho de que no haya ICloneable<T> podría ser una indicación en los pensamientos de Microsoft sobre ICloneable

9

Matt es correcto, no lo use. Crea tu propio método Copy() (o nombre similar) y hazlo perfectamente claro en tu API pública si tu método está creando una copia profunda o superficial de tu objeto.

27

La interfaz ICloneable por sí mismo no es muy útil, lo que equivale a decir que en realidad no hay muchas situaciones en las que es útil saber que un objeto es cloneable sin saber nada más sobre el asunto. Esta es una situación muy diferente de, por ejemplo, IEnumerable o IDisposable; hay muchas situaciones en las que es útil aceptar un IEnumerable sin saber nada más que la forma de enumerarlo.

Por otro lado, ICloneable puede ser útil cuando se aplica como una restricción genérica junto con otras restricciones. Por ejemplo, una clase base podría ser útil para varios derivados, algunos de los cuales podrían clonarse de forma útil y otros no. Si el tipo de base expuso una interfaz de clonación pública, cualquier tipo de derivado que no pudiera clonarse violaría el Principio de sustitución de Liskov. La forma de evitar este problema es hacer que el tipo de base soporte la clonación usando un método Protegido, y permitir que los tipos derivados implementen una interfaz de clonación pública como lo consideren apropiado.

Una vez que se logró, un método que quiere aceptar un objeto de un tipo WonderfulBase y necesita poder clonarlo, podría codificarse para aceptar un objeto WonderfulBase que admita clonación (utilizando un parámetro de tipo genérico con base -type y ICloneable restricciones). Aunque la interfaz ICloneable no indicaría la clonación profunda o superficial, la documentación para WonderfulBase indicaría si clonable WonderfulBase debe clonarse profunda o superficialmente. Esencialmente, la interfaz ICloneable no lograría nada que no se lograría definiendo ICloneableWonderfulBase, excepto que evitaría tener que definir diferentes nombres para cada clase base clonable diferente.

+3

+1 para el principio de Liskov – TheSilverBullet

Cuestiones relacionadas