Pourquoi devrais-je implémenter ICloneable en c #?

111

Pouvez-vous m'expliquer pourquoi je devrais hériter ICloneableet implémenter la Clone()méthode?

Si je veux faire une copie complète, ne puis-je pas simplement implémenter ma méthode? Disons MyClone()?

Pourquoi devrais-je hériter ICloneable? Quels sont les avantages? S'agit-il simplement de rendre le code "plus lisible"?

uinc
la source

Réponses:

117

Tu ne devrais pas. Microsoft recommande de ne pas l'implémenter ICloneablecar il n'y a aucune indication claire de l'interface si votre Cloneméthode effectue un clone "profond" ou "superficiel".

Voir ce billet de blog de Brad Abrams en 2003 (!) Pour plus d'informations.

Matt Hamilton
la source
4
Lien de retour vers l'article, qui est maintenant 404: web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/…
harpo
2
Un meilleur lien: blogs.msdn.microsoft.com/brada/2004/05/03/…
Eric Lippert
29

L' ICloneableinterface en elle - même n'est pas très utile, c'est-à-dire qu'il n'y a vraiment pas beaucoup de situations où il est utile de savoir qu'un objet est clonable sans rien savoir d'autre à son sujet. C'est une situation très différente de par exemple IEnumerableou IDisposable; il existe de nombreuses situations où il est utile d'accepter un IEnumerablesans rien savoir d'autre que de l'énumérer.

D'un autre côté, cela ICloneablepeut être utile lorsqu'il est appliqué en tant que contrainte générique avec d'autres contraintes. Par exemple, une classe de base pourrait utilement prendre en charge un certain nombre de dérivés, dont certains pourraient être utilement clonés et d'autres pas. Si le type de base lui-même exposait une interface de clonage publique, alors tout type dérivé qui ne pourrait pas être cloné violerait le principe de substitution de Liskov. Le moyen d'éviter ce problème consiste à faire en sorte que le type de base prenne en charge le clonage à l'aide d'une méthode Protected et autorise les types dérivés à implémenter une interface de clonage publique comme ils l'entendent.

Une fois que cela a été accompli, une méthode qui veut accepter un objet d'un WonderfulBasetype, et doit pouvoir le cloner, pourrait être codée pour accepter un objet WonderfulBase qui prend en charge le clonage (en utilisant un paramètre de type générique avec un type de base et des ICloneablecontraintes) . Bien que l' ICloneableinterface n'indique pas elle-même un clonage profond ou superficiel, la documentation pour WonderfulBaseindiquerait si le clonage WonderfulBasedoit être cloné profond ou superficiel. Essentiellement, l' ICloneableinterface n'accomplirait rien qui ne serait pas accompli en définissant ICloneableWonderfulBase, sauf qu'elle éviterait d'avoir à définir des noms différents pour chaque classe de base clonable différente.

supercat
la source
18

ICloneableest l'un de ces artefacts de la BCL qui a été controversé. Il n'y a aucune vraie raison IMHO de le mettre en œuvre. Cela dit, si je vais créer une méthode de clonage, je l'implémente ICloneableet je fournis ma propre version typée forte de Clone.

Le problème avec ICloneableest qu'il n'a jamais indiqué s'il Clones'agissait d'une copie superficielle ou profonde qui sont des choses très différentes. Le fait qu'il n'y ait aucune ICloneable<T>indication sur les réflexions de Microsoft sur ICloneable

JoshBerke
la source
9

Matt a raison, ne l'utilisez pas. Créez votre propre Copy()méthode (ou un nom similaire) et indiquez clairement dans votre API publique si votre méthode crée une copie profonde ou superficielle de votre objet.

John Rasch
la source