2009-03-30 11 views
106

Pouvez-vous m'expliquer pourquoi je devrais hériter de ICloneable et implémenter la méthode Clone()?Pourquoi devrais-je implémenter ICloneable dans C#?

Si je veux faire une copie en profondeur, ne puis-je pas implémenter ma méthode? Disons MyClone()?

Pourquoi devrais-je hériter de ICloneable? Quels sont les avantages? Est-ce juste une question de rendre le code "plus lisible"?

+0

** Voir aussi **: [La polémique ICloneable: une classe peut-elle être implémentée IClonable ou non?] (Http://www.sysexpand.com/?path=howto/implement-icloneable-or-not) – KyleMit

Répondre

111

Vous ne devriez pas. Microsoft déconseille d'implémenter ICloneable car l'interface ne dispose pas d'indications claires indiquant si votre méthode Clone exécute un clone «profond» ou «superficiel».

Voir this blog post from Brad Abrams en 2003 (!) Pour plus d'informations.

+4

Wayback lien vers l'article, qui est 404 maintenant: http://web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/archive/2003/04/09/49935.aspx – harpo

+1

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

18

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

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

9

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

27

L'interface ICloneable par lui-même est pas très utile, ce qui veut dire qu'il n'y a vraiment pas beaucoup de situations où il est utile de savoir qu'un objet est cloneable sans savoir quoi que ce soit d'autre à ce sujet. Ceci est une situation très différente de par exemple. IEnumerable ou IDisposable; Il existe de nombreuses situations où il est utile d'accepter un IEnumerable sans rien savoir d'autre que la façon de l'énumérer. Par contre, 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ées, dont certaines pourraient être utilement clonées, et d'autres ne le pourraient pas. Si le type de base exposait lui-même une interface de clonage publique, tout type dérivé qui ne pourrait pas être cloné violerait le principe de substitution de Liskov. La façon d'éviter ce problème est de faire en sorte que le type de base prenne en charge le clonage à l'aide d'une méthode Protected, et permettre aux types dérivés d'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 qui doit pouvoir le cloner, pourrait être codée pour accepter un objet WonderfulBase qui supporte le clonage (en utilisant un paramètre de type générique avec base -type et ICloneable contraintes). Bien que l'interface ICloneable n'indique pas elle-même un clonage profond ou superficiel, la documentation pour WonderfulBase indique si le clonage WonderfulBase doit être cloné en profondeur ou peu profond. Essentiellement, l'interface ICloneable n'accomplirait rien qui ne serait pas accompli en définissant ICloneableWonderfulBase, sauf qu'elle éviterait de devoir définir des noms différents pour chaque classe de base clonable différente.

+3

+1 pour le principe de Liskov – TheSilverBullet