web-dev-qa-db-fra.com

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

Pouvez-vous m'expliquer pourquoi je dois hériter de ICloneable et implémenter la méthode Clone()?

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

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

108
uinc

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

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

116
Matt Hamilton

L'interface ICloneable par lui-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 en savoir autre chose. Il s'agit d'une situation très différente, par exemple, IEnumerable ou IDisposable; il existe de nombreuses situations où il est utile d'accepter un IEnumerable sans savoir autre chose que comment l'énumérer.

D'un autre côté, ICloneable peut ê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 non. 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. Pour éviter ce problème, le clonage prend en charge le type de base à l'aide d'une méthode protégée et autorise les types dérivés à implémenter une interface de clonage publique comme bon leur semble.

Une fois cela fait, une méthode qui veut accepter un objet de type WonderfulBase, 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 type de base et ICloneable contraintes). Bien que l'interface ICloneable n'indique pas elle-même un clonage profond ou superficiel, la documentation de WonderfulBase indiquerait si le clonable WonderfulBase doit être cloné en profondeur ou en superficiel. Essentiellement, l'interface ICloneable 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.

29
supercat

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

Le problème avec ICloneable est qu'il n'est jamais indiqué si Clone était une copie superficielle ou profonde, ce qui est très différent. Le fait qu'il n'y ait pas de ICloneable<T> pourrait être une indication des réflexions de Microsoft sur ICloneable

18
JoshBerke

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

9
John Rasch