Ich habe darüber gelesen const
und static readonly
Felder . Wir haben einige Klassen, die nur konstante Werte enthalten. Wird für verschiedene Dinge in unserem System verwendet. Ich frage mich also, ob meine Beobachtung richtig ist:
Sollte diese Art von konstanten Werten immer sein static readonly
für alles gelten, was öffentlich ist? Und nur const
für interne / geschützte / private Werte verwenden?
Was empfehlen Sie? Sollte ich vielleicht sogar keine static readonly
Felder verwenden, sondern vielleicht Eigenschaften?
static readonly
: Versuchen Sie, eine Konstante in einer zu verwenden,IEnumerator
die ein Unrecheable auslösen würde,yield
und Sie erhalten einen gefürchteten "internen Compilerfehler" . Ich habe den Code außerhalb von Unity3D nicht getestet, aber ich vertraue darauf, dass dies entweder ein Mono- oder ein .NET- Fehler ist . Es ist dennoch ein C # -Problem.static readonly
kann in derswitch-case
Anweisung nicht alscase
Variable verwendet werden,const
ist für diesen Zweck erforderlich.static readonly
kann auch nicht als Attributparameter verwendet werdenAntworten:
public static readonly
Felder sind etwas ungewöhnlich;public static
Eigenschaften (mit nur aget
) wären häufiger (möglicherweise durch einprivate static readonly
Feld unterstützt).const
Werte werden direkt in die Anrufstelle gebrannt; das ist zweischneidig:Wenn sich der Wert nie ändert, ist const in Ordnung -
Zero
usw. machen Sie vernünftige consts; p Ansonsten sindstatic
Eigenschaften häufiger.quelle
readonly
Felder können nicht in switch / case-Anweisungen verwendet werden, sondern müssen vorhanden seinconst
.Ich würde verwenden,
static readonly
wenn sich der Verbraucher in einer anderen Baugruppe befindet. Dasconst
und den Verbraucher in zwei verschiedenen Baugruppen zu haben, ist eine gute Möglichkeit, sich in den Fuß zu schießen .quelle
internal const
oderpublic static readonly
abhängig von der gewünschten Sichtbarkeit.public const
(z. B. alles, was Teil eines Standards ist. Jedes Mal , wenn ich mit XML arbeite, gibt es einen Namespaces-Datei mit einer Reihe vonpublic const string
.) Im Allgemeinenpublic const
sollte sie jedoch nur verwendet werden, nachdem die Auswirkungen richtig berücksichtigt wurden.Einige relevantere Dinge zu beachten:
const int a
schreibgeschützt int a
quelle
ctor
einzigen.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 a non-const unterschiedliche Semantiken haben. Zum Beispiel:druckt aus
True
, während:schreibt
False
.Der Grund dafür ist, dass die Methode
x.Equals
zwei Überladungen aufweist, eine mitshort
(System.Int16
) und eine mitobject
(System.Object
). Nun ist die Frage, ob einer oder beide bei mir zutreffeny
Argument .Wenn
y
es sich um eine Konstante zur Kompilierungszeit (Literal) handelt,const
wird es wichtig, dass eine implizite Konvertierung vonint
nachshort
vorhandenint
ist , vorausgesetzt, dass es sich um eine Konstante handelt, und dass der C # -Compiler überprüft, ob ihr Wert im Bereich von ashort
(liegt welches42
ist). Siehe Konvertierungen impliziter konstanter Ausdrücke in der C # -Sprachenspezifikation. Beide Überlastungen müssen also berücksichtigt werden. Die ÜberlastungEquals(short)
wird bevorzugt (jedeshort
ist eineobject
, aber nicht alleobject
sindshort
). Wirdy
also in konvertiertshort
und diese Überlastung wird verwendet. DannEquals
vergleicht zweishort
von identischem Wert, und das ergibttrue
.Wenn
y
keine Konstante ist, existiert keine implizite Konvertierung vonint
nachshort
. Das liegt daran, dass ein im Allgemeinenint
zu groß sein kann, um in ein zu passenshort
. (Es gibt eine explizite Konvertierung, aber ich habe nicht gesagtEquals((short)y)
, das ist also nicht relevant.) Wir sehen, dass nur eine Überladung gilt, dieEquals(object)
eine. Alsoy
ist verpacktobject
. DannEquals
wird eine vergleichen ,System.Int16
um einSystem.Int32
, und da die Laufzeittypen stimmen nicht einmal, das wird nachgebenfalse
.Wir schließen daraus, dass in einigen (seltenen) Fällen das Ändern eines
const
Typelements in einstatic readonly
Feld (oder anders, wenn dies möglich ist) das Verhalten des Programms ändern kann.quelle
short x = 42;
legal zu machen . Denn dort haben Sie einint
, nämlich das Literal42
, das implizit in das verwandelt wirdshort x
. Aber dann könnten sie dies auf nur numerische Literale beschränkt haben; Sie haben sich jedoch dafür entschieden, auch Dinge zuzulassen, wieshort x = y;
woy
definiert istconst int y = 42;
, und dann haben sie dies erreicht.Zu beachten ist, dass const auf primitive / Werttypen beschränkt ist (Ausnahme: Zeichenfolgen).
quelle
const
könnte es auch für andere Typen verwendet werden, außer dass es auf null initialisiert werden muss, was es nutzlos macht :)System.Exception
? :)const
verwendet werden können, sindsbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
,decimal
,bool
, sowie alleenum
Arten.const
kann nicht für andere Werttypen wieDateTime
oderTimeSpan
oder verwendet werdenBigInteger
. Es kann auch nicht für dieIntPtr
Struktur verwendet werden (von einigen als "primitiver" Typ angesehen; der Begriff primitiver Typ ist in C # verwirrend). ↵↵ Dasconst
kann für alle Referenztypen verwendet werden . Wenn der Typ iststring
, kann ein beliebiger Zeichenfolgenwert angegeben werden. Andernfalls muss der Wert seinnull
.const
mit machen könnendefault
. Beistruct
Typen handelt es sich um eine Instanz, bei der alle Mitglieder auf die Standardwerte eingestellt sind.Statisch schreibgeschützt : Der Wert kann
static
zur Laufzeit über den Konstruktor geändert werden. Aber nicht durch die Mitgliedsfunktion.Konstante : Standardmäßig
static
. Der Wert kann von keiner Stelle aus geändert werden (Ctor, Funktion, Laufzeit usw. nirgendwo).Schreibgeschützt : Der Wert kann zur Laufzeit über den Konstruktor geändert werden. Aber nicht durch die Mitgliedsfunktion.
Sie können sich meine Repo: C # -Eigenschaftstypen ansehen .
quelle
Das
readonly
Schlüsselwort unterscheidet sich vomconst
Schlüsselwort. Einconst
Feld kann nur bei der Deklaration des Feldes initialisiert werden. Einreadonly
Feld kann entweder bei der Deklaration oder in einem Konstruktor initialisiert werden. Daher könnenreadonly
Felder je nach verwendetem Konstruktor unterschiedliche Werte haben. Während einconst
Feld eine Konstante zur Kompilierungszeit ist, kann dasreadonly
Feld auch für Laufzeitkonstanten verwendet werdenKurze und klare MSDN-Referenz hier
quelle
const
undreadonly
sind ähnlich, aber sie sind nicht genau gleich.Ein
const
Feld ist eine Konstante zur Kompilierungszeit, dh dieser Wert kann zur Kompilierungszeit berechnet werden. Einreadonly
Feld ermöglicht zusätzliche Szenarien, in denen während der Erstellung des Typs Code ausgeführt werden muss. Nach dem Bau areadonly
Feld nicht mehr geändert werden.Beispielsweise können
const
Mitglieder verwendet werden, um Mitglieder wie folgt zu definieren:Da Werte wie 3.14 und 0 Konstanten zur Kompilierungszeit sind. Betrachten Sie jedoch den Fall, in dem Sie einen Typ definieren und einige vorgefertigte Instanzen davon bereitstellen möchten. Beispielsweise möchten Sie möglicherweise eine Farbklasse definieren und "Konstanten" für gängige Farben wie Schwarz, Weiß usw. bereitstellen. Dies ist mit const-Elementen nicht möglich, da die rechten Seiten keine Konstanten zur Kompilierungszeit sind. Man könnte dies mit regulären statischen Mitgliedern tun:
Aber dann gibt es nichts, was einen Kunden von Color davon abhält, sich damit zu beschäftigen, vielleicht indem er die Schwarz-Weiß-Werte vertauscht. Dies würde natürlich andere Kunden der Color-Klasse bestürzen. Die Funktion "Nur Lesen" behebt dieses Szenario.
Durch einfaches Einfügen des
readonly
Schlüsselworts in die Deklarationen behalten wir die flexible Initialisierung bei und verhindern gleichzeitig, dass Client-Code durcheinander gerät.Es ist interessant festzustellen, dass const-Elemente immer statisch sind, während ein schreibgeschütztes Element entweder statisch sein kann oder nicht, genau wie ein reguläres Feld.
Es ist möglich, ein einzelnes Schlüsselwort für diese beiden Zwecke zu verwenden, dies führt jedoch entweder zu Versionsproblemen oder zu Leistungsproblemen. Nehmen wir für einen Moment an, dass wir ein einziges Schlüsselwort für dieses (const) verwendet haben und ein Entwickler schrieb:
und ein anderer Entwickler schrieb Code, der sich auf A stützte:
Kann der generierte Code nun auf der Tatsache beruhen, dass AC eine Konstante zur Kompilierungszeit ist? Kann die Verwendung von AC einfach durch den Wert 0 ersetzt werden? Wenn Sie dazu "Ja" sagen, bedeutet dies, dass der Entwickler von A die Art und Weise, wie AC initialisiert wird, nicht ändern kann - dies bindet die Hände des Entwicklers von A ohne Erlaubnis.
Wenn Sie zu dieser Frage "Nein" sagen, wird eine wichtige Optimierung übersehen. Vielleicht ist der Autor von A sicher, dass AC immer Null sein wird. Die Verwendung von const und readonly ermöglicht es dem Entwickler von A, die Absicht anzugeben. Dies sorgt für ein besseres Versionsverhalten und eine bessere Leistung.
quelle
Ich bevorzuge es, const zu verwenden, wann immer ich kann, was, wie oben erwähnt, auf wörtliche Ausdrücke oder etwas beschränkt ist, das keine Bewertung erfordert.
Wenn ich auf diese Einschränkung stoße , greife ich mit einer Einschränkung auf statisch schreibgeschützt zurück . Ich würde im Allgemeinen eine öffentliche statische Eigenschaft mit einem Getter und einem privaten statischen schreibgeschützten Feld verwenden, wie Marc hier erwähnt .
quelle
Referenz: c-Scharfe Ecke
quelle
Ein statisches schreibgeschütztes Feld ist vorteilhaft, wenn Sie anderen Assemblys einen Wert zur Verfügung stellen, der sich in einer späteren Version möglicherweise ändert.
Angenommen, die Assembly
X
stellt eine Konstante wie folgt bereit:Wenn Assembly auf diese Konstante
Y
verweistX
und diese verwendet, wird der Wert 2.3Y
beim Kompilieren in Assembly gebacken . Dies bedeutet, dass, wennX
später mit der auf 2.4 eingestellten Konstante neu kompiliertY
wird, der alte Wert von 2.3 bisY
zur Neukompilierung weiterhin verwendet wird. Ein statisches schreibgeschütztes Feld vermeidet dieses Problem.Eine andere Sichtweise ist, dass jeder Wert, der sich in Zukunft ändern könnte, per Definition nicht konstant ist und daher nicht als einer dargestellt werden sollte.
quelle
const:
schreibgeschützt:
quelle
Const : const Variablenwerte müssen zusammen mit der Deklaration definiert werden und danach ändert sie sich nicht mehr. const sind implizit statisch, sodass wir ohne Erstellen einer Klasseninstanz auf sie zugreifen können. Dies hat zum Zeitpunkt der Kompilierung einen Wert
Schreibgeschützt : Nur - Lese - Variablenwert können wir definieren , während als auch mit dem Konstruktor zur Laufzeit zu erklären. schreibgeschützte Variablen können ohne Klasseninstanz nicht zugreifen.
Statisch schreibgeschützt : statische schreibgeschützte Variablenwerte, die wir beim Deklarieren sowie nur über den statischen Konstruktor definieren können, jedoch nicht mit einem anderen Konstruktor. Auf diese Variablen können wir auch zugreifen, ohne eine Klasseninstanz zu erstellen (als statische Variablen).
Nur 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 unter dem folgenden Link
https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/
quelle
In C # .Net gibt es einen geringfügigen Unterschied zwischen const- und statischen schreibgeschützten Feldern
const muss zur Kompilierungszeit mit value initialisiert werden.
const ist standardmäßig statisch und muss mit einem konstanten Wert initialisiert werden, der später nicht mehr geändert werden kann. Es kann nicht mit allen Datentypen verwendet werden. Zum Beispiel DateTime. Es kann nicht mit dem Datentyp DateTime verwendet werden.
readonly kann als statisch deklariert werden, ist aber nicht erforderlich. Zum Zeitpunkt der Deklaration ist keine Initialisierung erforderlich. Sein Wert kann einmal mit dem Konstruktor zugewiesen oder geändert werden. Es besteht also die Möglichkeit, den Wert des schreibgeschützten Feldes einmal zu ändern (spielt keine Rolle, ob es statisch ist oder nicht), was mit const nicht möglich ist.
quelle
Konstanten sind wie der Name schon sagt, Felder, die sich nicht ändern und normalerweise zur Kompilierungszeit im Code statisch definiert werden.
Schreibgeschützte Variablen sind Felder, die sich unter bestimmten Bedingungen ändern können.
Sie können entweder initialisiert werden, wenn Sie sie zum ersten Mal als Konstante deklarieren. In der Regel werden sie jedoch während der Objektkonstruktion im Konstruktor initialisiert.
Sie können nach der Initialisierung unter den oben genannten Bedingungen nicht mehr geändert werden.
Statisch schreibgeschützt klingt für mich nach einer schlechten Wahl, denn wenn es statisch ist und sich nie ändert, verwenden Sie es einfach public const. Wenn es sich ändern kann, ist es keine Konstante. Abhängig von Ihren Anforderungen können Sie entweder read verwenden -nur oder nur eine reguläre Variable.
Ein weiterer wichtiger Unterschied ist, dass eine Konstante zur Klasse gehört, während die schreibgeschützte Variable zur Instanz gehört!
quelle
Eine Konstante (die zur Kompilierungszeit bestimmt wird) kann in Fällen verwendet werden, in denen eine schreibgeschützte Statik nicht möglich ist, wie in switch-Anweisungen oder Attributkonstruktoren. Dies liegt daran, dass schreibgeschützte Felder nur zur Laufzeit aufgelöst werden und einige Codekonstrukte eine Gewähr für die Kompilierungszeit erfordern. Eine schreibgeschützte Statik kann in einem Konstruktor berechnet werden, was häufig eine wesentliche und nützliche Sache ist. Der Unterschied ist funktional, wie ihre Verwendung meiner Meinung nach sein sollte.
In Bezug auf die Speicherzuweisung scheint es zumindest bei Zeichenfolgen (die ein Referenztyp sind) keinen Unterschied zu geben, dass beide intern sind und auf die eine internierte Instanz verweisen.
Persönlich ist meine Standardeinstellung schreibgeschützt, da sie für mich semantischer und logischer ist, zumal die meisten Werte zur Kompilierungszeit nicht benötigt werden. Übrigens ist die öffentliche Readonly-Statik nicht ungewöhnlich oder überhaupt nicht ungewöhnlich, wie in der markierten Antwort angegeben: Zum Beispiel
System.String.Empty
eine.quelle
Ein weiterer Unterschied zwischen der Deklaration von const und static readonly besteht in der Speicherzuordnung.
Ein statisches Feld gehört zum Typ eines Objekts als zu einer Instanz dieses Typs. Sobald die Klasse zum ersten Mal referenziert wird, "lebt" das statische Feld für den Rest der Zeit im Speicher, und dieselbe Instanz des statischen Felds wird von allen Instanzen des Typs referenziert.
Andererseits gehört ein const- Feld "zu einer Instanz des Typs.
Wenn die Speicherung der Freigabe für Sie wichtiger ist, verwenden Sie lieber const . Wenn Geschwindigkeit, dann statisch schreibgeschützt verwenden .
quelle