Frage Statische Readonly vs const


Ich habe es gelesen const und static readonly Felder. Wir haben einige Klassen, die nur konstante Werte enthalten. Verwendet für verschiedene Dinge in unserem System. Ich frage mich also, ob meine Beobachtung richtig ist:

Sollte diese Art von konstanten Werten immer sein static readonly für alles was öffentlich ist? Und nur benutzen const für interne / geschützte / private Werte?

Was empfehlen Sie? Sollte ich vielleicht gar nicht benutzen static readonly Felder, sondern lieber Eigenschaften verwenden?


1201
2018-04-16 11:21


Ursprung


Antworten:


public static readonly Felder sind etwas ungewöhnlich; public static Eigenschaften (mit nur a get) wäre häufiger (vielleicht unterstützt durch eine private static readonly Feld).

const Werte werden direkt in die Call-Site gebrannt; Das ist zweischneidig:

  • es ist nutzlos, wenn der Wert zur Laufzeit abgerufen wird, vielleicht von Config
  • Wenn Sie den Wert von const ändern, müssen Sie alle Clients neu erstellen
  • aber es kann schneller sein, da es einen Methodenaufruf vermeidet ...
  • ... die manchmal von der JIT manchmal inline gewesen sein könnte

Wenn der Wert wird noch nie ändern, dann ist const in Ordnung - Zero usw. machen angemessene Konflikte; p static Eigenschaften sind häufiger.


828
2018-04-16 11:24



ich würde ... benutzen static readonly wenn die Verbraucher ist in einer anderen Versammlung. Das haben const und das Verbraucher in zwei verschiedenen Baugruppen ist ein schöner Weg zu erschieß dich in den Fuß.


199
2018-04-16 12:57



Einige andere Dinge

const int a 

  • muss initialisiert werden
  • Die Initialisierung muss zur Kompilierzeit erfolgen

readonly int a

  • kann den Standardwert verwenden, ohne zu initialisieren
  • Initialisierung kann zur Laufzeit erfolgen

173
2018-04-16 11:36



Dies ist nur eine Ergänzung zu den anderen Antworten. Ich werde sie nicht wiederholen (jetzt vier Jahre später).

Es gibt Situationen, in denen a const und eine Nicht-Konstante haben unterschiedliche Semantiken. Beispielsweise:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

druckt aus True, wohingegen:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

schreibt False.

Der Grund ist, dass die Methode x.Equals hat zwei Überladungen, eine, die einnimmt short (System.Int16) und einer, der ein object (System.Object). Jetzt stellt sich die Frage, ob einer oder beide mit meinem zutreffen y Streit.

Wann y ist eine Kompilierzeitkonstante (Literal), die const Fall wird es wichtig, dass es eine implizite Konvertierung gibt von  int  zu  short vorausgesetzt dass das int ist eine Konstante und vorausgesetzt, dass der C # -Compiler überprüft, ob sein Wert innerhalb des Bereichs von a liegt short (welche 42 ist). Sehen Implizite konstante Ausdruckskonvertierungen in der C # -Sprachspezifikation. Also müssen beide Überlastungen berücksichtigt werden. Die Überlastung Equals(short) ist bevorzugt (beliebig short ist ein object, aber nicht alles object sind short). Damit y wird konvertiert in shortund diese Überladung wird verwendet. Dann Equals vergleicht zwei short von identischem Wert, und das gibt true.

Wann y ist keine Konstante, nein implizit Umwandlung von int zu short existiert. Das ist, weil im Allgemeinen ein intkann zu groß sein, um in einen zu passen short. (Ein explizit Umwandlung existiert, aber ich habe nicht gesagt Equals((short)y), das ist also nicht relevant.) Wir sehen, dass nur eine Überladung zutrifft, die Equals(object) ein. Damit y ist eingerahmt object. Dann Equals wird vergleichen a System.Int16 zu einem System.Int32und da die Laufzeittypen nicht übereinstimmen, wird dies nachgeben false.

Wir kommen zu dem Schluss, dass in einigen (seltenen) Fällen ein const Geben Sie member in a ein static readonly Feld (oder umgekehrt, wenn das möglich ist) kann das Verhalten des Programms ändern.


151
2017-09-11 14:52



Eine Sache zu beachten ist const ist auf primitive / Werttypen beschränkt (Ausnahme sind Strings)


82
2018-04-16 11:28



Das readonly Stichwort ist anders als die const Stichwort. EIN const Feld kann nur bei der Deklaration des Feldes initialisiert werden. EIN readonly Feld kann entweder an der Deklaration oder in einem Konstruktor initialisiert werden. Deshalb, readonly Felder können abhängig vom verwendeten Konstruktor unterschiedliche Werte haben. Auch, während a const field ist eine Kompilierzeitkonstante, die readonly Feld kann für Laufzeitkonstanten verwendet werden

Kurze und klare MSDN-Referenz hier


23
2017-11-14 18:58



Nur statisches Lesen : Wert kann durch geändert werden static Konstruktor zur Laufzeit. Aber nicht durch Memberfunktion.

Konstante : Standardmäßig static. Der Wert kann nicht von irgendwo geändert werden (Ctor, Function, Runtime usw. No-Where).

Schreibgeschützt : Der Wert kann zur Laufzeit über Konstruktor geändert werden. Aber nicht durch Memberfunktion.

Sie können sich mein Repo ansehen: C # -Eigenschaftstypen.


16
2018-01-12 17:14



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

EIN const field ist eine Kompilierzeitkonstante, was bedeutet, dass dieser Wert zur Kompilierzeit berechnet werden kann. EIN readonly Feld aktiviert zusätzliche Szenarien, in denen während der Erstellung des Typs Code ausgeführt werden muss. Nach dem Bau, a readonly Feld kann nicht geändert werden.

Zum Beispiel, const Mitglieder können verwendet werden, um Mitglieder zu definieren wie:

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

Da Werte wie 3.14 und 0 Kompilierzeitkonstanten sind. Beachten Sie jedoch den Fall, in dem Sie einen Typ definieren und einige vorgefertigte Instanzen davon bereitstellen möchten. Z. B. könnten Sie eine Farbklasse definieren und "Konstanten" für gebräuchliche Farben wie Schwarz, Weiß usw. bereitstellen. Dies ist nicht möglich mit konstanten Elementen, da die rechten Seiten keine Kompilierzeitkonstanten sind. Man könnte dies mit regulären statischen Mitgliedern tun:

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, was einen Kunden von Color davon abhalten könnte, damit herumzuspielen, vielleicht durch den Austausch der Schwarz-Weiß-Werte. Unnötig zu erwähnen, dass dies für andere Kunden der Color-Klasse zu Bestürzung führen würde. Die "readonly" -Funktion adressiert dieses Szenario.

Durch die Einführung der readonly Schlüsselwort in den Deklarationen, behalten wir die flexible Initialisierung bei, während wir verhindern, dass Client-Code herumfummelt.

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 konstante Elemente immer statisch sind, während ein schreibgeschütztes Element entweder statisch sein kann oder nicht, genau wie ein normales Feld.

Es ist möglich, ein einzelnes Schlüsselwort für diese beiden Zwecke zu verwenden, dies führt jedoch entweder zu Versionierungsproblemen oder zu Leistungsproblemen. Angenommen, wir haben ein einzelnes Schlüsselwort dafür verwendet (const) und ein Entwickler schrieb:

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

und ein anderer Entwickler schrieb Code, der auf A basierte:

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

Kann der generierte Code nun davon abhängen, dass A.C eine Kompilierzeitkonstante ist? D. h., Kann die Verwendung von A.C einfach durch den Wert 0 ersetzt werden? Wenn Sie "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 diese Frage mit "nein" beantworten, wird eine wichtige Optimierung verpasst. Vielleicht ist der Autor von A positiv, dass A.C immer Null sein wird. Die Verwendung von const und readonly erlaubt dem Entwickler von A, die Absicht zu spezifizieren. Dies verbessert das Versionsverhalten und verbessert die Leistung.


13
2017-09-28 08:19



Meine Präferenz ist zu verwenden const wann immer ich kann, was wie oben erwähnt auf wörtliche Ausdrücke beschränkt ist oder etwas, das keine Auswertung erfordert.

Wenn ich mich gegen diese Einschränkung aufwärme, dann stoße ich auf statisch nur lesbarmit einem Vorbehalt. Ich würde normalerweise eine öffentliche statische Eigenschaft mit einem Getter und einer Unterstützung verwenden private statische readonly Feld wie Marc erwähnt Hier.


11
2018-04-16 12:48