1595 Stimmen

'Statisch schreibgeschützt' vs. 'const'

Ich habe mich über const und static readonly Felder informiert. Wir haben einige Klassen, die nur konstante Werte enthalten. Sie werden für verschiedene Dinge in unserem System verwendet. Daher frage ich mich, ob meine Beobachtung korrekt ist:

Sollten diese Art von konstanten Werten immer static readonly sein für alles, was öffentlich ist? Und nur const für internal/protected/private Werte verwenden?

Was empfehlen Sie? Sollte ich vielleicht sogar keine static readonly Felder verwenden, sondern vielleicht Eigenschaften?

8 Stimmen

Hier ist ein sehr interessanter Einzelfall, den ich gerade zugunsten von static readonly gefunden habe: Versuchen Sie, ein const innerhalb eines IEnumerator zu verwenden, das ein unerreichbares yield auslösen würde, und Sie erhalten einen gefürchteten "Interner Compilerfehler". Ich habe den Code nicht außerhalb von Unity3D getestet, aber ich vertraue darauf, dass dies entweder ein Mono oder ein .NET Fehler ist. Es handelt sich jedoch um ein C# Problem.

4 Stimmen

10 Stimmen

Eine weitere Unterschied besteht darin, dass Sie eine const-Zeichenfolge in einem Switch verwenden können, aber keine static readonly-Zeichenfolge.

40voto

Yeasin Abedin Punkte 1609

Statisch Nur Lesen:

Der Wert kann durch einen statischen Konstruktor zur Laufzeit geändert werden. Aber nicht durch eine Member-Funktion.

Konstant:

Standardmäßig statisch. Ein Wert kann von überall aus nicht geändert werden (Konstruktor, Funktion, Laufzeit usw. nirgendwo).

Nur Lesen:

Der Wert kann durch einen Konstruktor zur Laufzeit geändert werden. Aber nicht durch eine Member-Funktion.

Sie können einen Blick auf mein Repository werfen: C# Eigenschaftstypen.

1 Stimmen

Schlechte Nachricht... defekter Link!

2 Stimmen

32voto

yazanpro Punkte 4052

Das Schlüsselwort readonly unterscheidet sich vom Schlüsselwort const. Ein const-Feld kann nur bei der Deklaration des Feldes initialisiert werden. Ein readonly-Feld kann entweder bei der Deklaration oder in einem Konstruktor initialisiert werden. Daher können readonly-Felder je nach verwendeten Konstruktor unterschiedliche Werte haben. Außerdem ist ein const-Feld ein Kompilierungszeitkonstante, während das readonly-Feld für Laufzeitkonstanten verwendet werden kann.

Aus dieser kurzen und klaren MSDN-Referenz.

23voto

Ramesh Rajendran Punkte 34781

const und readonly sind ähnlich, aber sie sind nicht genau das Gleiche.

Ein const Feld ist eine Kompilierungszeitkonstante, was bedeutet, dass der Wert zur Kompilierungszeit berechnet werden kann. Ein readonly Feld ermöglicht zusätzliche Szenarien, bei denen bestimmter Code während der Konstruktion des Typs ausgeführt werden muss. Nach der Konstruktion kann ein readonly Feld nicht geändert werden.

Zum Beispiel können const Elemente verwendet werden, um Elemente wie:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

Da Werte wie 3.14 und 0 Kompilierungszeitkonstanten sind. Allerdings, überlegen Sie sich den Fall, in dem Sie einen Typ definieren und einige vorgefertigte Instanzen davon bereitstellen möchten. Zum Beispiel könnte man eine Color-Klasse definieren und "Konstanten" für gebräuchliche Farben wie Schwarz, Weiß usw. bereitstellen. Dies ist mit const Elementen nicht möglich, da die rechten Seiten keine Kompilierungszeitkonstanten sind. Dies könnte mit regulären statischen Elementen gemacht werden:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red   = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

Aber dann gibt es nichts, das einen Client von Color daran hindert, damit herumzuspielen, vielleicht indem er die Werte für Schwarz und Weiß vertauscht. Unnötig zu sagen, dies würde für andere Clients der Color-Klasse Ärger verursachen. Das "readonly"-Feature behandelt dieses Szenario.

Indem wir einfach das readonly Schlüsselwort in den Deklarationen einführen, bewahren wir die flexible Initialisierung und verhindern, dass der Clientcode damit herumspielt.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red   = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

Es ist interessant festzustellen, dass const Elemente immer statisch sind, während ein readonly Element entweder statisch oder nicht sein kann, genauso wie ein reguläres Feld.

Es ist möglich, ein einzelnes Schlüsselwort für diese beiden Zwecke zu verwenden, aber dies führt entweder zu Versionsproblemen oder Leistungsproblemen. Nehmen wir einmal an, dass wir für dies ein einzelnes Schlüsselwort (const) verwenden und ein Entwickler schreibt:

public class A
{
    public static const C = 0;
}

Und ein anderer Entwickler schreibt Code, der auf A beruht:

public class B
{
    static void Main() => Console.WriteLine(A.C);
}

Kann der generierte Code darauf vertrauen, dass A.C eine Kompilierungszeitkonstante ist? D.h., kann die Verwendung von A.C einfach durch den Wert 0 ersetzt werden? Wenn Sie darauf "ja" sagen, dann bedeutet das, dass der Entwickler von A die Art und Weise, wie A.C initialisiert wird, nicht ändern kann -- dies bindet die Hände des Entwicklers von A ohne Erlaubnis.

Wenn Sie darauf "nein" sagen, dann wird eine wichtige Optimierung verpasst. Vielleicht ist der Autor von A sicher, dass A.C immer Null sein wird. Die Verwendung von sowohl const als auch readonly erlaubt es dem Entwickler von A, die Absicht anzugeben. Dies führt zu einem besseren Versionsverhalten und auch zu einer besseren Leistung.

16voto

Peter Meyer Punkte 25181

Meine Präferenz ist es, const zu verwenden, wann immer möglich, was, wie in früheren Antworten erwähnt, auf literalen Ausdrücken oder etwas Beschränktes zurückzuführen ist, was keine Auswertung erfordert.

Wenn ich auf diese Beschränkung stoße, dann weiche ich auf static readonly aus, mit einer Ausnahme. Generell würde ich eine öffentliche statische Eigenschaft mit einem Getter und einem unterstützenden private static readonly Feld verwenden, wie Marc hier erwähnt hier.

13voto

user1756922 Punkte 169

Konst: Konstante Variablenwerte müssen zusammen mit der Deklaration definiert werden und ändern sich danach nicht. Konstanten sind implizit statisch, sodass wir ohne Instanziierung einer Klasse darauf zugreifen können. Dies hat einen Wert zur Kompilierungszeit.

Schreibgeschützt: Wir können schreibgeschützte Variablenwerte sowohl bei der Deklaration als auch mit dem Konstruktor zur Laufzeit definieren. Auf schreibgeschützte Variablen kann ohne Instanziierung einer Klasse nicht zugegriffen werden.

Statisch schreibgeschützt: Wir können statische schreibgeschützte Variablenwerte sowohl bei der Deklaration als auch nur durch einen statischen Konstruktor definieren, aber nicht mit einem anderen Konstruktor. Wir können auch auf diese Variablen zugreifen, ohne eine Klasseninstanz zu erstellen (als statische Variablen).

Statisch schreibgeschützt ist die bessere Wahl, wenn wir die Variablen in verschiedenen Assemblys verwenden müssen. Bitte überprüfen Sie die vollständigen Details im folgenden Blog-Beitrag:

Konstante Strings - eine sehr bequeme Art, sich selbst ins Bein zu schießen

1 Stimmen

Könnten Sie mir bitte sagen, warum Sie die Antwort heruntergevotet haben, damit ich mich selbst und hier aktualisieren kann?

1 Stimmen

Nicht das DV, aber es könnte sein, dass diese Antwort hier nicht wirklich etwas zu den bereits umfassenden Antworten hinzufügt.

0 Stimmen

Tatsächlich erinnern Sie sich in Java Ende der 90er Jahre hatten wir in einem Projekt mehrere Personen, die verschiedene Jars mit Klassen erstellten, die miteinander interagierten (sich gegenseitig referenzierten) und public const string hatte Versionsprobleme, da sie herumkopiert wurden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X