Was sind die Vorteile, wenn eine Mitgliedsvariable als schreibgeschützt deklariert wird? Schützt es nur vor jemandem, der seinen Wert während des Lebenszyklus der Klasse ändert, oder führt die Verwendung dieses Schlüsselworts zu einer Verbesserung der Geschwindigkeit oder Effizienz?
295
readonly
Felder von Strukturtypen im Vergleich zu veränderlichen Feldern, die einfach nicht mutiert sind, eine Leistungseinbuße bedeuten, dareadonly
der Compiler beim Aufrufen eines Mitglieds eines Felds vom Werttyp eine Kopie des Felds erstellt und das Feld aufruft Mitglied dazu.Antworten:
Das
readonly
Schlüsselwort wird verwendet, um eine Mitgliedsvariable als Konstante zu deklarieren, ermöglicht jedoch die Berechnung des Werts zur Laufzeit. Dies unterscheidet sich von einer mit demconst
Modifikator deklarierten Konstante , deren Wert zur Kompilierungszeit festgelegt werden muss. Mit könnenreadonly
Sie den Wert des Felds entweder in der Deklaration oder im Konstruktor des Objekts festlegen, zu dem das Feld gehört.Verwenden Sie es auch, wenn Sie keine externen DLLs neu kompilieren müssen, die auf die Konstante verweisen (da diese beim Kompilieren ersetzt werden).
quelle
Ich glaube nicht, dass die Verwendung eines schreibgeschützten Feldes zu Leistungssteigerungen führt. Es ist lediglich eine Überprüfung, um sicherzustellen, dass dieses Feld nicht auf einen neuen Wert gezeigt werden kann, sobald das Objekt vollständig erstellt wurde.
"Readonly" unterscheidet sich jedoch stark von anderen Arten der schreibgeschützten Semantik, da sie zur Laufzeit von der CLR erzwungen wird. Das schreibgeschützte Schlüsselwort wird auf .initonly kompiliert, was durch die CLR überprüft werden kann.
Der eigentliche Vorteil dieses Schlüsselworts besteht darin, unveränderliche Datenstrukturen zu generieren. Unveränderliche Datenstrukturen können per Definition nicht geändert werden, sobald sie erstellt wurden. Dies macht es sehr einfach, über das Verhalten einer Struktur zur Laufzeit nachzudenken. Beispielsweise besteht keine Gefahr, eine unveränderliche Struktur an einen anderen zufälligen Teil des Codes zu übergeben. Sie können es nie ändern, so dass Sie zuverlässig gegen diese Struktur programmieren können.
Hier ist ein guter Eintrag über einen der Vorteile der Unveränderlichkeit: Einfädeln
quelle
Die Verwendung
readonly
bietet keine offensichtlichen Leistungsvorteile , zumindest keine, die ich jemals irgendwo erwähnt habe. Dies dient nur dazu, genau das zu tun, was Sie vorschlagen, um Änderungen nach der Initialisierung zu verhindern.Dies ist insofern von Vorteil, als Sie robusteren und besser lesbaren Code schreiben können. Der wahre Vorteil solcher Dinge liegt in der Arbeit in einem Team oder bei der Wartung. Wenn Sie etwas
readonly
deklarieren, das dem Einfügen eines Vertrags für die Verwendung dieser Variablen in den Code ähnelt. Stellen Sie sich vor, Sie fügen Dokumentation auf die gleiche Weise hinzu wie andere Schlüsselwörter wieinternal
oderprivate
. Sie sagen "Diese Variable sollte nach der Initialisierung nicht geändert werden" und erzwingen darüber hinaus sie außerdem.Wenn Sie also eine Klasse erstellen und einige Mitgliedsvariablen als beabsichtigt markieren
readonly
, verhindern Sie, dass Sie selbst oder ein anderes Teammitglied später einen Fehler machen, wenn sie Ihre Klasse erweitern oder ändern. Meiner Meinung nach ist dies ein Vorteil, der sich lohnt (auf Kosten der zusätzlichen Komplexität der Sprache, wie doofledorfer in den Kommentaren erwähnt).quelle
Um es sehr praktisch auszudrücken:
Wenn Sie eine Konstante in DLL A verwenden und DLL B auf diese Konstante verweist, wird der Wert dieser Konstante in DLL B kompiliert. Wenn Sie DLL A mit einem neuen Wert für diese Konstante erneut bereitstellen, verwendet DLL B weiterhin den ursprünglichen Wert.
Wenn Sie in dll A und dll B eine schreibgeschützte Referenz verwenden, die schreibgeschützt ist, wird diese schreibgeschützt immer zur Laufzeit nachgeschlagen. Dies bedeutet, dass DLL B diesen neuen Wert verwendet, wenn Sie DLL A mit einem neuen Wert für diesen Readonly erneut bereitstellen.
quelle
const
kann es zu einem Leistungsgewinn kommenreadonly
. Hier ist eine etwas tiefere Erklärung mit Code: dotnetperls.com/readonlyreadonly
Feldern zu speichern . Sie können nicht speichern ,new object();
in einconst
und das macht Sinn , weil Sie nicht nicht-Wert Dinge wie Verweise in andere Baugruppen während der Kompilierung backen kann , ohne Identität zu verändern.Es gibt einen möglichen Fall, in dem der Compiler eine Leistungsoptimierung basierend auf dem Vorhandensein des schreibgeschützten Schlüsselworts vornehmen kann.
Dies gilt nur, wenn das schreibgeschützte Feld ebenfalls als statisch markiert ist . In diesem Fall kann der JIT-Compiler davon ausgehen, dass sich dieses statische Feld niemals ändert. Der JIT-Compiler kann dies beim Kompilieren der Methoden der Klasse berücksichtigen.
Typisches Beispiel: Ihre Klasse könnte ein statisches schreibgeschütztes IsDebugLoggingEnabled- Feld haben, das im Konstruktor initialisiert wird (z. B. basierend auf einer Konfigurationsdatei). Sobald die eigentlichen Methoden JIT-kompiliert sind, kann der Compiler ganze Teile des Codes auslassen, wenn die Debug-Protokollierung nicht aktiviert ist.
Ich habe nicht überprüft, ob diese Optimierung tatsächlich in der aktuellen Version des JIT-Compilers implementiert ist, daher handelt es sich nur um Spekulationen.
quelle
Beachten Sie, dass schreibgeschützt nur für den Wert selbst gilt. Wenn Sie also einen Referenztyp verwenden, schützt schreibgeschützt die Referenz nur vor Änderungen. Der Status der Instanz ist nicht schreibgeschützt.
quelle
Vergessen Sie nicht, dass es eine Problemumgehung gibt, mit der die
readonly
Felder außerhalb von Konstruktoren festgelegt werden könnenout
Parametern festzulegen.Ein bisschen chaotisch aber:
Weitere Diskussion hier: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx
quelle
out
..Überraschenderweise kann Readonly tatsächlich zu langsamerem Code führen, wie Jon Skeet beim Testen seiner Noda Time-Bibliothek feststellte. In diesem Fall dauerte ein Test, der in 20 Sekunden ausgeführt wurde, nur 4 Sekunden, nachdem er schreibgeschützt entfernt wurde.
https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/
quelle
readonly struct
in C # 7.2 a ist, der Vorteil, dass das Feld nicht schreibgeschützt ist, wegfällt.Wenn Sie einen vordefinierten oder vorberechneten Wert haben, der während des gesamten Programms gleich bleiben muss, sollten Sie eine Konstante verwenden. Wenn Sie jedoch einen Wert haben, der zur Laufzeit angegeben werden muss, der jedoch einmal zugewiesen wurde, sollte er während des gesamten Programms gleich bleiben schreibgeschützt. Wenn Sie beispielsweise die Programmstartzeit zuweisen müssen oder einen vom Benutzer angegebenen Wert bei der Objektinitialisierung speichern müssen und ihn auf weitere Änderungen beschränken müssen, sollten Sie schreibgeschützt verwenden.
quelle
Hinzufügen eines grundlegenden Aspekts zur Beantwortung dieser Frage:
Eigenschaften können als schreibgeschützt ausgedrückt werden, indem der
set
Operator weggelassen wird . In den meisten Fällen müssen Sie dasreadonly
Schlüsselwort also nicht zu den Eigenschaften hinzufügen :Im Gegensatz dazu: Felder benötigen das
readonly
Schlüsselwort, um einen ähnlichen Effekt zu erzielen:Ein Vorteil des Markierens eines Feldes als
readonly
kann darin bestehen, eine ähnliche Schreibschutzstufe wie eine Eigenschaft ohneset
Operator zu erreichen - ohne das Feld in eine Eigenschaft ändern zu müssen, wenn dies aus irgendeinem Grund gewünscht wird.quelle
Seien Sie vorsichtig mit privaten schreibgeschützten Arrays. Wenn diese einen Client als Objekt verfügbar machen (Sie können dies für COM-Interop wie ich tun), kann der Client Array-Werte bearbeiten. Verwenden Sie die Clone () -Methode, wenn Sie ein Array als Objekt zurückgeben.
quelle
ReadOnlyCollection<T>
anstelle eines Arrays bereit.ImmutableArray<T>
, wodurch das Boxen an eine Schnittstelle (IReadOnlyList<T>
) oder das Umschließen einer Klasse (ReadOnlyCollection
) vermieden wird . Die Leistung ist vergleichbar mit nativen Arrays: blogs.msdn.microsoft.com/dotnet/2013/06/24/…WPF kann einen Leistungsvorteil bieten, da keine teuren DependencyProperties erforderlich sind. Dies kann besonders bei Sammlungen hilfreich sein
quelle
Ein weiterer interessanter Teil der Verwendung der schreibgeschützten Markierung kann darin bestehen, das Feld vor der Initialisierung in Singleton zu schützen.
Zum Beispiel in Code von csharpindepth :
readonly spielt eine kleine Rolle beim Schutz des Feldes Singleton vor zweimaliger Initialisierung. Ein weiteres Detail ist, dass Sie für das erwähnte Szenario keine const verwenden können, da const die Erstellung während der Kompilierungszeit erzwingt, Singleton jedoch die Erstellung zur Laufzeit vornimmt.
quelle
readonly
kann bei der Deklaration initialisiert werden oder den Wert nur vom Konstruktor erhalten. Im Gegensatzconst
dazu muss es initialisiert und gleichzeitig deklariert werden.readonly
hat allesconst
hat, plus KonstruktorinitialisierungCode https://repl.it/HvRU/1
quelle