Ich mag das Unveränderlichkeitskonzept, aber manchmal frage ich mich, wenn eine Anwendung nicht parallel sein soll, sollte man es vermeiden, Dinge unveränderlich zu machen?
Wenn eine Anwendung nicht multi-threaded ist, werden Sie nicht von Problemen mit dem gemeinsamen Status geplagt, oder?
Oder ist Unveränderlichkeit ein Konzept wie OOP, das Sie entweder ganz oder gar nicht benutzen? Ausschließen der Fälle, in denen etwas nicht aufgrund von Gebrauch / Leistung, etc. unveränderlich sein sollte.
Ich stehe vor dieser Frage, wenn ich eine Anwendung für mich selbst schreibe, die ziemlich groß ist (vielleicht 1-2K Zeilen).
Ich liebe Unveränderlichkeit, weil es bedeutet, dass ich nicht dem Code anderer Leute vertrauen muss, um mich nicht mit Dingen herumzuschlagen, von denen ich erwarte, dass sie gleich bleiben.
Wenn Sie ein Objekt an eine andere Komponente übergeben, z. B. List<T>
, sind Sie der Gnade dieser Komponente ausgeliefert. Dies ist besonders wichtig, wenn Sie Sammlungen als Eigenschaften zurückgeben.
Es gibt nichts, was einen Verbraucher dieser Klasse davon abhält, die Sammlung unter mir zu beseitigen. Sogar das Umschalten des Rückgabetyps auf IEnumerable<Bar>
ist nicht völlig sicher. Es gibt nichts, was einen schlecht geschriebenen Code davon abhält, ihn wieder in List<T>
zu schreiben und .Clear () aufzurufen.
Wenn ich jedoch möchte, dass die Sammlung konsistent bleibt, könnte ich sie wie folgt umschreiben:
%Vor%Jetzt bin ich sicher davor, anderen Code zu vertrauen, um meine Klasse falsch zu benutzen. Sie können es nicht vermasseln.
Ich mag den Vorteil der Unveränderlichkeit, dass Sie ihn nur einmal validieren müssen - bei der Erstellung des Objekts. Das ist eigentlich ein großer Bonus.
Ein wesentlicher Vorteil der Unveränderbarkeit ist, dass man das Eigentum an unveränderlichen Objekten nicht verfolgen muss. Sie existieren nur, solange sie jemand braucht, und verschwinden dann ins Nichts, wenn sie nicht mehr benötigt werden. In vielen Fällen bedeutet die Verwendung eines Garbage-Collectors, dass es nicht notwendig ist, einen ausdrücklichen Code zu schreiben, der sich mit dem Besitz von veränderbaren Objekten beschäftigt (die größte Ausnahme sind die, die IDisposable
implementieren). In vielen Fällen ist es sehr schwierig, korrekten Code in Objekte zu schreiben die einen veränderlichen Zustand haben, haben keinen klar definierten "Besitzer". Verwirrung darüber, wem der Status von veränderbaren Objekten gehört, kann eine sehr häufige Fehlerquelle sein; Wenn Sie unveränderliche Objekte verwenden (abgesehen von einigen, die IDisposable
implementieren), können Sie Besitzprobleme generell ignorieren.
Ein weiterer zu berücksichtigender Punkt ist, dass es viel einfacher ist, über einen veränderlichen Verweis auf ein semantisch unveränderliches Objekt oder einen unveränderlichen Verweis auf ein veränderbares Objekt nachzudenken, als über einen veränderbaren Verweis auf ein veränderbares Objekt nachzudenken. Wenn ein veränderbarer Verweis auf veränderbare Objekte vorhanden ist, kann es oft unklar sein, ob der richtige Ansatz zum Aktualisieren des Zustands darin besteht, das Objekt einfach zu mutieren oder seinen Zustand in ein neues Objekt zu kopieren, das mutieren und die Referenz aktualisieren. In einigen Fällen gibt es Umstände, die jede Art von Operation erfordern (wie bei List<T>
, die manchmal ein Array durch ein größeres ersetzt, aber in der Regel Aktualisierungen vornimmt), aber ein solcher Ansatz funktioniert nur, wenn der Typ exklusiv hält Kontrolle über die fraglichen veränderbaren Objekte. Es ist oft hilfreicher, einen unveränderlichen Verweis auf einen veränderlichen Typ zu haben (in diesem Fall kann Code die Referenz möglicherweise über einen Nur-Lese-Wrapper anderen Objekten zugänglich machen, die eine "Live-Ansicht" seines Zustands wünschen) oder a veränderlicher Bezug auf ein Objekt, das unveränderlich ist oder zumindest während der Lebensdauer der Referenz niemals mutiert wird.
Tags und Links .net c# performance immutability