Ich frage mich, wie Unveränderlichkeit definiert ist? Wenn die Werte nicht öffentlich angezeigt werden, also nicht geändert werden können, reicht das?
Können die Werte innerhalb des Typs geändert werden, nicht vom Kunden des Typs?
Oder kann man sie nur in einem Konstruktor setzen? Wenn ja, ist es in den Fällen der doppelten Initialisierung (mit dem this
Schlüsselwort auf Strukturen usw.) immer noch in Ordnung für unveränderliche Typen?
Wie kann ich garantieren, dass der Typ 100% unveränderlich ist?
Wenn die Werte nicht öffentlich angezeigt werden, also nicht geändert werden können, reicht das?
Nein, weil Sie Lesezugriff benötigen.
Können die Werte innerhalb des Typs geändert werden, nicht vom Kunden des Typs?
Nein, weil das immer noch Mutation ist.
Oder kann man sie nur in einem Konstruktor setzen?
Ding ding! Mit dem zusätzlichen Punkt, dass unveränderliche Typen oft Methoden haben, die neue Instanzen konstruieren und zurückgeben, und haben oft zusätzliche Konstruktoren, die speziell für diese Methoden mit internal
markiert sind.
Wie kann ich garantieren, dass der Typ 100% unveränderlich ist?
In .Net ist es schwierig, eine Garantie wie diese zu bekommen, weil Sie mit reflection private Mitglieder modifizieren (mutieren) können.
Die vorherigen Poster haben bereits erklärt, dass Sie Ihren Feldern im Konstruktor Werte zuweisen sollten und dann die Finger davon lassen sollten. Aber das ist manchmal leichter gesagt als getan. Angenommen, Ihr unveränderliches Objekt macht eine Eigenschaft vom Typ List<string>
verfügbar. Darf diese Liste geändert werden? Und wenn nicht, wie kontrollieren Sie es?
Eric Lippert hat in seinem Blog eine Reihe von Posts über Unveränderlichkeit in C # geschrieben, die Sie vielleicht interessant finden: finden Sie den ersten Teil hier .
Eine Sache, die ich bei all diesen Antworten vielleicht übersehen habe, ist, dass ich ein Objekt als unveränderlich betrachten kann, selbst wenn sich sein interner Zustand ändert - solange diese internen Änderungen für den "Client" -Code nicht sichtbar sind.
Zum Beispiel ist die System.String
-Klasse unveränderlich, aber ich denke, es wäre erlaubt, den Hash-Code für eine Instanz zu cachen, so dass der Hash nur beim ersten Aufruf von GetHashCode()
berechnet wird. Beachten Sie, dass, soweit ich weiß, die System.String
-Klasse dies nicht tut, aber ich denke, dass sie als unveränderlich betrachtet werden kann und immer noch betrachtet werden kann. Natürlich müsste jede dieser Änderungen in einer Thread-sicheren Weise gehandhabt werden (in Übereinstimmung mit dem nicht beobachtbaren Aspekt der Änderungen).
Um ehrlich zu sein, kann ich mir nicht viele Gründe vorstellen, warum man diese Art von "unsichtbarer Veränderlichkeit" möchte oder braucht.
Hier ist die Definition der Unveränderlichkeit von Wikipedia ( link )
"In der objektorientierten und funktionalen Programmierung ist ein unveränderliches Objekt ein Objekt, dessen Zustand nach der Erstellung nicht geändert werden kann."
Nachdem das Objekt erstellt wurde, kann im Wesentlichen keine seiner Eigenschaften geändert werden. Ein Beispiel ist die String-Klasse. Sobald ein String-Objekt erstellt wurde, kann es nicht mehr geändert werden. Jede Operation, die damit ausgeführt wird, erzeugt tatsächlich ein neues String-Objekt.
Viele Fragen dort. Ich werde versuchen, sie alle einzeln zu beantworten:
"Ich frage mich, wie Unveränderlichkeit definiert ist?" - Direkt von der Wikipedia-Seite (und einer sehr genauen / prägnanten Definition)
Ein unveränderliches Objekt ist ein Objekt, dessen Status nach der Erstellung nicht geändert werden kann.
"Wenn die Werte nicht öffentlich angezeigt werden, also nicht geändert werden können, reicht das?" - Nicht ganz. Es kann nicht in irgendwie geändert werden , so dass Sie sicherstellen müssen, dass Methoden / Funktionen den Zustand des Objekts nicht ändern, und wenn Sie Operationen ausführen, immer eine neue Instanz zurückgeben.
"Können die Werte innerhalb des Typs geändert werden, nicht vom Kunden des Typs?" - Technisch kann es nicht innerhalb oder durch einen Verbraucher des Typs geändert werden. In der Praxis existieren Typen wie System.String
(ein Referenztyp für die Materie), die für fast alle praktischen Zwecke als veränderbar angesehen werden können, wenn auch nicht in der Theorie.
"Oder kann man sie nur in einem Konstruktor setzen?" - Ja, in der Theorie ist dies der einzige Ort, an dem der Status (Variablen) eingestellt werden kann.
"Wenn ja, ist es in den Fällen der doppelten Initialisierung (mit dem Schlüsselwort this auf Strukturen usw.) immer noch in Ordnung für unveränderliche Typen?" - Ja, das ist immer noch völlig in Ordnung, weil es alles Teil des Initialisierungs (Erstellungs) prozesses ist und die Instanz erst zurückgegeben wird, wenn sie beendet ist.
"Wie kann ich garantieren, dass der Typ 100% unveränderlich ist?" - Die folgenden Bedingungen sollten dies gewährleisten. (Jemand bitte darauf hinweisen, wenn ich einen vermisse.)
private
behalten (nicht einmal protected
ist akzeptabel, da abgeleitete Klassen dann den Status ändern können). Hinweis: Sie können die Unveränderlichkeit abgeleiteter Typen nicht sicherstellen, da sie neue Variablen definieren können. Dies ist ein Grund dafür, einen beliebigen Typ zu markieren, um sicherzustellen, dass er als sealed
unveränderlich ist, so dass keine abgeleitete Klasse irgendwo im Code als unveränderlicher Basis-Typ betrachtet werden kann.
Ich hoffe, das hilft.
Die Definition der Unveränderlichkeit kann auf Google gefunden werden.
Beispiel:
unveränderlich - buchstäblich, nicht in der Lage zu ändern.
www.filosofia.net/materiales/rec/glosaen.htm
Im Hinblick auf unveränderbare Datenstrukturen lautet die typische Definition "einmal schreiben, mehrere lesen". Anders ausgedrückt: Wenn Sie das einmal erstellt haben, kann es nicht mehr geändert werden.
Es gibt einige Fälle, die leicht in der Grauzone liegen. Beispielsweise werden .NET-Zeichenfolgen als unveränderlich betrachtet, da sie nicht geändert werden können. StringBuilder ändert jedoch intern ein Zeichenfolgenobjekt.
Ein Unveränderliches ist im Wesentlichen eine Klasse, die sich dazu zwingt, aus ihrem eigenen Code endgültig zu sein. Sobald es da ist, kann nichts geändert werden. In meinem Wissen werden Dinge im Konstruktor festgelegt und das ist es dann. Ich sehe nicht, wie etwas anders unveränderlich sein könnte.
Es gibt leider keine unveränderlichen Schlüsselwörter in c # / vb.net, obwohl es diskutiert wurde, aber wenn es keine autoproperties gibt und alle Felder mit readonly deklariert sind (schreibgeschützte Felder können nur im Konstruktor zugewiesen werden) modfier und alle Felder Wird von einem unveränderlichen Typ erklärt, haben Sie Ihre eigene Unveränderlichkeit versichert.
Ein unveränderliches Objekt ist eines, dessen beobachtbarer Zustand niemals durch irgendeine plausible Sequenz der Codeausführung geändert werden kann. Ein unveränderlicher Typ ist einer, der garantiert, dass alle Instanzen, die der Außenwelt ausgesetzt sind, unveränderlich sein werden (diese Anforderung wird oft als Bedingung angegeben, dass der Zustand des Objekts nur in seinem Konstruktor gesetzt werden darf; dies ist bei Objekten mit private Konstruktoren, noch ist es ausreichend bei Objekten, die während der Konstruktion externe Methoden auf sich selbst anwenden.)
Ein Punkt, den andere Antworten vernachlässigt haben, ist jedoch eine Definition des Zustands eines Objekts. Wenn Foo
eine Klasse ist, besteht der Zustand von List<Foo>
aus der Folge von Objektidentitäten , die darin enthalten sind. Wenn der einzige Verweis auf eine bestimmte List<Foo>
-Instanz von Code gehalten wird, der weder dazu führt, dass diese Sequenz geändert wird, noch ihn einem Code aussetzt, der dies tun könnte, wird diese Instanz unabhängig davon, ob die Foo
-Objekte sind, unveränderlich sein darauf bezogen sind veränderbar oder unveränderlich.
Um eine Analogie zu verwenden: Wenn eine Liste von Fahrzeug-VINs (Vehicle Identification Numbers) auf manipulationssicherem Papier gedruckt ist, wäre die Liste selbst unveränderlich, obwohl es Autos nicht sind. Selbst wenn die Liste heute zehn rote Autos enthält, könnte sie morgen zehn blaue Autos enthalten; sie würden jedoch immer noch dieselben zehn Autos sein .
Tags und Links .net c# immutability