Ich frage mich, warum MemberwiseClone als geschützt definiert ist. Dies bedeutet, dass nur abgeleitete Typen darauf zugreifen können. Was ist das Problem, wenn es als öffentlich definiert wurde?Warum ist MemberwiseClone in System.Object geschützt?
Antwort
Pavel Minaev's answer from another discussion:
Andere haben bereits erklärt, über MemberwiseClone, aber niemand gab die Erklärung, warum es geschützt ist. Ich werde versuchen, die Begründung zu geben.
Das Problem hier ist, dass MemberwiseClone nur blind den Zustand kopiert. In vielen Fällen ist dies unerwünscht. Zum Beispiel könnte das Objekt ein privates Feld haben, das ein Verweis auf eine Liste ist. Eine flache Kopie, wie sie MemberwiseClone ausführt, würde dazu führen, dass ein neues Objekt auf dieselbe Liste verweist - und die Klasse könnte durchaus geschrieben sein, dass sie nicht erwartet, dass die Liste mit anderen geteilt wird.
Oder ein Objekt kann eine Art ID-Feld haben, generiert im Konstruktor - wieder, wenn Sie das Klonen, erhalten Sie zwei Objekte mit der gleichen ID, die zu allen Arten von seltsamen Fehlern in Methoden unter der Annahme, dass ID ist einzigartig.
Oder Sie haben ein Objekt, das einen Socket oder einen Dateistream öffnet und einen Verweis darauf speichert. MemberwiseClone kopiert einfach die Referenz - und Sie können sich vorstellen, dass zwei Objekte, die versuchen, Aufrufe an denselben Stream zu verschachteln, nicht gut enden werden.
Kurz gesagt, "Klonen" ist keine wohldefinierte Operation für beliebige Objekte. Die Tatsache, dass memberwise operator = standardmäßig für alle Klassen in C++ vorgesehen ist, ist eher lästig, da die Leute zu oft vergessen, dass sie da ist, und sie nicht für Klassen deaktiviert, für die Kopieren nicht sinnvoll oder gefährlich ist (und es gibt überraschend viele solcher Klassen).
Wenn MemberwiseClone nicht existiert, gibt es keine andere Möglichkeit, als Reflection für eine vererbbare Klasse zu verwenden, die eine polymorphe Klonoperation unterstützt, außer dass jede abgeleitete Klasse explizit eine angeben muss. Wenn eine abgeleitete Klasse keine Klonoperation bereitstellt, führt dies zu einem unerwarteten Verhalten. Angenommen, Fahrzeug, Auto und ToyotaCar bieten explizite Klonierungsmethoden, ToyotaCorolla jedoch nicht. Hat jemand ein Objekt vom Typ ToyotaCorolla und versucht es zu klonen, wäre das Ergebnis ein ToyotaCar. Da es Situationen gibt, in denen polymorphes Klonen erforderlich ist und es unbequem wäre, jede abgeleitete Klasse einer klonbaren Klasse explizit zu unterstützen, ist MemberwiseClone ein notwendiger Bestandteil des Frameworks.
Auf der anderen Seite kann MemberwiseClone auch gefährlich sein. Das Ausführen eines MemberwiseClone für ein Objekt führt häufig zu einem beschädigten Objekt. Der Versuch, beliebige Eigenschaften oder Methoden des defekten Objekts zu verwenden, kann das Original beschädigen.
Es ist schade, dass Microsoft eine gute Praxis für das Klonen nicht besser definiert hat. Es ist möglich und nicht allzu schwierig, ein polymorphes Klonierungsmuster zu entwerfen, das keine geerbten Klassen benötigt, um explizit etwas zu tun, es sei denn, sie fügen Felder hinzu, die eine spezielle Behandlung erfordern, oder wenn ein Aufrufer den deklarierten Rückgabetyp der Klonmethode erwartet die abgeleitete Klasse. Während die letztere Situation häufig eine Voraussetzung ist, führt ein Fehler bei der expliziten Implementierung der erforderlichen Methode zu einem Kompilierungsfehler und nicht zu fehlerhaftem Laufzeitverhalten.
BTW, Microsoft scheint zu glauben, dass etwas über tiefe Klonen kloniert. Es ist nicht. Der Aufruf von "Clone" für ein Objekt sollte das Objekt in die Tiefe klonen, die notwendig ist, um seine definierte Semantik zu erhalten. Das Klonen eines FileCabinet (Of T) sollte ein neues FileCabinet ergeben, das für die Methoden von FileCabinet unabhängig vom Original ist, aber es sollte die gleichen T-Instanzen enthalten wie das Original.Da der Zweck eines Archivs darin besteht, Instanzen von T zu halten, aber nichts damit zu tun, sollte das Klonen des Gehäuses nicht bedeuten, den Inhalt zu klonen (aber es würde das Klonen irgendwelcher Arrays bedeuten, die der Schrank selbst verwendet, um den Inhalt zu halten).
Übrigens, wenn ich meine druthers hätte, würde es eine Schnittstelle in .Net geben, die durch String und primitive Typen (plus viele andere), genannt DeepClonableIfMutable, implementiert wird. Bei Anwendung auf einen String oder ein anderes Grundelement würde die DeepCloneIfMutable-Methode einfach das ursprüngliche Objekt zurückgeben. Benutzerdefinierte unveränderbare Objekte könnten DeepClonableIfMuguable implementieren, um sich ähnlich zu verhalten, während veränderbare Objekte sich selbst und alle verschachtelten DeepClonableIfMutable-Instanzen tiefklonen.
- Eine Menge Dinge machen keinen Sinn zu klonen; alles, was
- Die meisten Objekte auf einem nicht verwalteten Griff, zum Beispiel spricht richtig ist wirklich schwer, wenn Sie außerhalb von ein paar einfachen Fällen gehen
- nicht brauchen
- Tief Kopieren etwas ein Klon-Anlage in vielen Fällen gibt es bessere Metaphern als blinde Klone
- manuell Klon Anlage auf Ihre Typen hinzufügen, die es brauchen trivial einfach ist
Für mich dann, es ist ein Kinderspiel, dass dies nicht der öffentlichen API standardmäßig hinzugefügt werden soll.
- 1. Warum ist CollectionView.CollectionChanged geschützt?
- 2. Was ist in TypeScript geschützt?
- 3. C++ Fehler: Basisfunktion ist geschützt
- 4. Warum ist intern geschützt nicht restriktiver als intern?
- 5. build.gradle ist vor Dekompilierung geschützt?
- 6. Ist Qooxdoo gegen XSS geschützt?
- 7. Was virtuelle neuen geschützt ist
- 8. Warum wurde keine Clone-Methode in System.Object eingefügt?
- 9. Warum nicht 'geschützt' oder 'privat' in PHP verwenden?
- 10. Ist dieser Code gegen SQL-Injektion geschützt?
- 11. Warum geschützt schützt das Mitglied in dieser Klasse nicht?
- 12. Warum geschützt schützt das Mitglied in dieser Klasse nicht?
- 13. Warum ist die DoubleBuffered-Eigenschaft in einer DataGridView standardmäßig auf "false" gesetzt und warum ist sie geschützt?
- 14. Boxen und Unboxing, warum sind die Ausgänge nicht beide "System.Object"?
- 15. Ist pac-man noch urheberrechtlich geschützt?
- 16. Konvertierung in abgeleitete Klasse unzugänglich, wenn Basisklasse geschützt ist
- 17. Geschützt Untername.ValueChanged nicht aktualisiert
- 18. WCF bekannter Typ von System.Object in Config
- 19. Unterschied zwischen dynamic und System.Object
- 20. Bearbeiten geschützt Mitglied in php
- 21. LINQ to Entities erkennt nicht die Methode 'System.String Format (System.String, System.Object, System.Object)'
- 22. Wie privat und geschützt ist in C++ implementiert
- 23. Warum sollten Konstrukteure abstrakter Klassen geschützt werden, nicht öffentlich?
- 24. geschützt/öffentliche Inner Klassen
- 25. Sind UIs urheberrechtlich geschützt?
- 26. Elternzugang Kind privat/geschützt
- 27. Gibt es einen Unterschied zwischen geschützt intern und intern geschützt?
- 28. kann Konstruktor nicht als geschützt oder privat definieren! Warum?
- 29. Warum wird var zu System.Object in "foreach (var row in table.Rows)" ausgewertet?
- 30. ein Passwort geschützt Öffnen