Warum sollte ich ICloneable in c # implementieren?

110

Können Sie mir erklären, warum ich ICloneabledie Clone()Methode erben und implementieren sollte ?

Kann ich meine Methode nicht einfach implementieren, wenn ich eine tiefe Kopie erstellen möchte? Sagen wir MyClone()?

Warum sollte ich von erben ICloneable? Was sind die Vorteile? Geht es nur darum, Code "lesbarer" zu machen?

uinc
quelle

Antworten:

117

Das solltest du nicht. Microsoft rät von der Implementierung ab, ICloneableda auf der Benutzeroberfläche nicht eindeutig angegeben ist, ob Ihre CloneMethode einen "tiefen" oder einen "flachen" Klon ausführt.

Weitere Informationen finden Sie in diesem Blogbeitrag von Brad Abrams aus dem Jahr 2003 (!).

Matt Hamilton
quelle
4
Wayback-Link zum Artikel, der jetzt 404 ist: web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/…
harpo
2
Ein besserer Link: blogs.msdn.microsoft.com/brada/2004/05/03/…
Eric Lippert
29

Die ICloneableBenutzeroberfläche selbst ist nicht sehr nützlich, das heißt, es gibt wirklich nicht viele Situationen, in denen es nützlich ist zu wissen, dass ein Objekt klonbar ist, ohne etwas anderes darüber zu wissen. Dies ist eine ganz andere Situation als zB IEnumerableoder IDisposable; Es gibt viele Situationen, in denen es nützlich ist, eine zu akzeptieren, IEnumerableohne etwas anderes zu wissen, als sie aufzuzählen.

Andererseits ICloneablekann es nützlich sein, wenn es zusammen mit anderen Einschränkungen als generische Einschränkung angewendet wird. Beispielsweise könnte eine Basisklasse eine Reihe von Derivaten sinnvoll unterstützen, von denen einige sinnvoll geklont werden könnten und einige nicht. Wenn der Basistyp selbst eine öffentliche Klonschnittstelle verfügbar macht, verstößt jeder abgeleitete Typ, der nicht geklont werden kann, gegen das Liskov-Substitutionsprinzip. Um dieses Problem zu vermeiden, muss der Basistyp das Klonen mithilfe einer geschützten Methode unterstützen und abgeleiteten Typen ermöglichen, eine öffentliche Klonschnittstelle nach eigenem Ermessen zu implementieren.

Sobald dies erreicht ist, könnte eine Methode, die ein Objekt eines WonderfulBaseTyps akzeptieren möchte und in der Lage sein muss, es zu klonen, so codiert werden, dass sie ein WonderfulBase-Objekt akzeptiert, das das Klonen unterstützt (unter Verwendung eines generischen Typparameters mit Basistyp und ICloneableEinschränkungen). . Obwohl die ICloneableSchnittstelle selbst kein tiefes oder flaches Klonen WonderfulBaseanzeigen würde, würde die Dokumentation für angeben, ob das Klonen tief oder flach WonderfulBasegeklont werden sollte. Im Wesentlichen ICloneablewürde die Schnittstelle nichts erreichen, was durch Definieren nicht erreicht werden könnte ICloneableWonderfulBase, außer dass sie vermeiden müsste, unterschiedliche Namen für jede unterschiedliche klonbare Basisklasse zu definieren.

Superkatze
quelle
18

ICloneableist eines dieser kontroversen Artefakte in der BCL. IMHO gibt es keinen wirklichen Grund, es umzusetzen. Wenn ich eine Klonmethode erstellen möchte, implementiere ich diese ICloneableund stelle meine eigene stark typisierte Version von zur Verfügung Clone.

Das Problem mit ICloneableist, dass nie angegeben wird, ob Clonees sich um eine flache oder eine tiefe Kopie handelt, die sehr unterschiedliche Dinge sind. Die Tatsache, dass es keine gibt, ICloneable<T>könnte einen Hinweis auf Microsofts Gedanken zu ICloneable geben

JoshBerke
quelle
9

Matt ist richtig, benutze es nicht. Erstellen Sie Ihre eigene Copy()Methode (oder einen ähnlichen Namen) und machen Sie in Ihrer öffentlichen API klar, ob Ihre Methode eine tiefe oder flache Kopie Ihres Objekts erstellt.

John Rasch
quelle