Was ist der Unterschied zwischen const und readonly in C #?

1362

Was ist der Unterschied zwischen constund readonlyin C #?

Wann würden Sie eins über das andere verwenden?

Schreibgeschützt
quelle
Ich musste einige Antworten nachschlagen, um diesen Link zu finden, aber es ist eine gute. Eric Lipperts Einstellung zur Unveränderlichkeit in C #
Frank Bryce
2
@donstack, tatsächlich nach der C # Referenz , kann ein Nur - Lese - Feld zugewiesen werden , und sie mehrmals innerhalb der Felddeklarations und Konstruktor neu zugewiesen.
Marques

Antworten:

1289

Abgesehen von dem offensichtlichen Unterschied von

  • Das Deklarieren des Werts zum Zeitpunkt einer Definition für einen constVS- readonlyWert kann dynamisch berechnet werden, muss jedoch zugewiesen werden, bevor der Konstruktor beendet wird. Danach wird er eingefroren.
  • 'const's sind implizit static. Sie verwenden eine ClassName.ConstantNameNotation, um darauf zuzugreifen.

Es gibt einen subtilen Unterschied. Betrachten Sie eine Klasse, die in definiert ist AssemblyA.

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyBverweist AssemblyAund verwendet diese Werte im Code. Wenn dies kompiliert ist,

  • im Falle des constWertes ist es wie ein Suchen-Ersetzen, der Wert 2 wird in die AssemblyBIL des 'eingebrannt' . Dies bedeutet, dass ich morgen I_CONST_VALUEauf 20 aktualisieren werde . AssemblyBhätte noch 2 bis ich es neu kompiliere .
  • im Falle des readonlyWertes ist es wie refein Speicherort. Der Wert wird nicht in AssemblyBdie IL eingebrannt . Dies bedeutet, dass bei einer Aktualisierung des Speicherorts AssemblyBder neue Wert ohne Neukompilierung abgerufen wird . Wenn I_RO_VALUEalso auf 30 aktualisiert wird, müssen Sie nur erstellen AssemblyA. Alle Clients müssen nicht neu kompiliert werden.

Wenn Sie also sicher sind, dass sich der Wert der Konstante nicht ändert, verwenden Sie a const.

public const int CM_IN_A_METER = 100;

Wenn Sie jedoch eine Konstante haben, die sich ändern kann (z. B. Genauigkeit), oder verwenden Sie im Zweifelsfall a readonly.

public readonly float PI = 3.14;

Update: Aku muss erwähnt werden, weil er zuerst darauf hingewiesen hat. Außerdem muss ich einstecken, wo ich das gelernt habe. Effektives C # - Bill Wagner

Gishu
quelle
77
Der staticPunkt scheint der wichtigste und nützlichste Punkt zu sein -consts are implicitly static
LCJ
28
Der Teil über Referenzwerte ist der wichtigste. Konstantenwerte können weg optimiert werden.
CodingBarfield
22
readonlyVariablen können außerhalb des Konstruktors geändert werden (Reflektion). Es ist nur der Compiler, der versucht, Sie daran zu hindern, die Variable außerhalb des Konstruktors zu ändern.
Bitterblue
12
@ mini-me- readonlyVariablen dürfen nach Abschluss des Konstruktors auch durch Reflektion nicht mehr geändert werden. Die Laufzeit erzwingt dies nicht. Die Laufzeit kommt auch nicht zu erzwingen , dass Sie sich nicht ändern string.Emptyzu "Hello, world!", aber ich würde behaupten , noch nicht , dass dies macht string.Emptymodifizierbar, oder dass Code sollte nicht davon ausgehen , dass string.Emptyimmer eine leere Zeichenfolge sein.
7
blogs.msmvps.com/jonskeet/2014/07/16/… ist eine interessante Lektüre nur die Gemeinkosten von readonly
CAD Kerl
275

Es gibt eine Gotcha mit Konstanten! Wenn Sie auf eine Konstante aus einer anderen Assembly verweisen, wird deren Wert direkt in die aufrufende Assembly kompiliert. Auf diese Weise ändert sich die Konstante in der aufgerufenen Assembly nicht, wenn Sie sie in der aufrufenden Assembly aktualisieren!

aku
quelle
8
Bei der Dekompilierung (Reflector, ILSpy, ..) wird NIEMALS auf eine Konstante verwiesen, unabhängig von derselben Assembly oder einer anderen Assembly. Daher können Sie die Verwendung einer Konstante in kompiliertem Code überhaupt nicht analysieren.
springy76
159

Konstanten

  • Konstanten sind standardmäßig statisch
  • Sie müssen zur Kompilierungszeit einen Wert haben (Sie können z. B. 3,14 * 2 haben, aber keine Methoden aufrufen).
  • Könnte innerhalb von Funktionen deklariert werden
  • Werden in jede Assembly kopiert, die sie verwendet (jede Assembly erhält eine lokale Kopie der Werte)
  • Kann in Attributen verwendet werden

Schreibgeschützte Instanzfelder

  • Muss einen festgelegten Wert haben, wenn der Konstruktor beendet wird
  • Werden beim Erstellen einer Instanz ausgewertet

Statische schreibgeschützte Felder

  • Werden ausgewertet, wenn die Codeausführung auf die Klassenreferenz trifft (wenn eine neue Instanz erstellt oder eine statische Methode ausgeführt wird)
  • Muss einen ausgewerteten Wert haben, bis der statische Konstruktor fertig ist
  • Es wird nicht empfohlen, ThreadStaticAttribute auf diese zu setzen (statische Konstruktoren werden nur in einem Thread ausgeführt und legen den Wert für seinen Thread fest; alle anderen Threads haben diesen Wert nicht initialisiert).
splattne
quelle
58

Nur um hinzuzufügen, macht ReadOnly für Referenztypen nur die Referenz schreibgeschützt, nicht die Werte. Zum Beispiel:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

quelle
Gibt es einen anderen Referenztyp als den string, den Sie als Konstante verwenden könnten?
springy76
Sie können constmit anderen Referenztypen als Zeichenfolge haben, aber die Konstante kann nur den Wert haben null.
Mike Rosoft
40

Das erklärt es . Zusammenfassung: const muss zur Deklarationszeit initialisiert werden, schreibgeschützt kann auf dem Konstruktor initialisiert werden (und hat daher je nach verwendetem Konstruktor einen anderen Wert).

EDIT: Siehe Gishus Gotcha oben für den subtilen Unterschied

Vinko Vrsalovic
quelle
32

const: Kann nirgendwo geändert werden.

readonly: Dieser Wert kann nur im Konstruktor geändert werden. Kann in normalen Funktionen nicht geändert werden.

Deepthi
quelle
26

Es gibt eine kleine Gotcha mit Readonly. Ein schreibgeschütztes Feld kann innerhalb der Konstruktoren mehrfach festgelegt werden. Auch wenn der Wert in zwei verschiedenen verketteten Konstruktoren festgelegt ist, ist er weiterhin zulässig.


public class Sample {
    private readonly string ro;

    public Sample() {
        ro = "set";
    }

    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}
Mike Zwei
quelle
26

Ein konstantes Mitglied wird zur Kompilierungszeit definiert und kann zur Laufzeit nicht geändert werden. Konstanten werden mit dem constSchlüsselwort als Feld deklariert und müssen beim Deklarieren initialisiert werden.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Ein readonlyMitglied ist insofern wie eine Konstante, als es einen unveränderlichen Wert darstellt. Der Unterschied besteht darin, dass ein readonlyMitglied zur Laufzeit in einem Konstruktor initialisiert werden kann und auch beim Deklarieren initialisiert werden kann.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • Sie können nicht als deklariert werden static(sie sind implizit statisch).
  • Der Wert der Konstante wird zur Kompilierungszeit ausgewertet
  • Konstanten werden nur bei der Deklaration initialisiert

schreibgeschützt

  • Sie können entweder auf Instanzebene oder statisch sein
  • Der Wert wird zur Laufzeit ausgewertet
  • readonly kann in der Deklaration oder durch Code im Konstruktor initialisiert werden
Sujit
quelle
6
Sie können nicht statisch sein , sie sind statisch. Sie sollten static const int i = 0;
klarstellen
Können Sie erklären, warum constDeklarationen nicht innerhalb von Methoden abgegeben werden können?
Minh Tran
21

Eine Konstante ist eine Konstante zur Kompilierungszeit, während schreibgeschützt die Berechnung eines Werts zur Laufzeit und die Festlegung im Konstruktor oder Feldinitialisierer ermöglicht. Ein 'const' ist also immer konstant, aber 'readonly' ist schreibgeschützt, sobald es zugewiesen wurde.

Eric Lippert vom C # -Team hat weitere Informationen zu verschiedenen Arten der Unveränderlichkeit

Wheelie
quelle
15

Hier ist ein weiterer Link, der zeigt, dass const nicht versionssicher oder für Referenztypen relevant ist.

Zusammenfassung :

  • Der Wert Ihrer const-Eigenschaft wird zur Kompilierungszeit festgelegt und kann zur Laufzeit nicht geändert werden
  • Const kann nicht als statisch markiert werden - das Schlüsselwort gibt an, dass sie statisch sind, im Gegensatz zu schreibgeschützten Feldern, die dies können.
  • Const kann nichts anderes als Werttypen (primitive Typen) sein
  • Das schreibgeschützte Schlüsselwort markiert das Feld als unveränderlich. Die Eigenschaft kann jedoch im Konstruktor der Klasse geändert werden
  • Das schreibgeschützte Schlüsselwort kann auch mit static kombiniert werden, damit es sich wie eine Konstante verhält (zumindest auf der Oberfläche). Es gibt einen deutlichen Unterschied, wenn Sie die IL zwischen den beiden betrachten
  • const-Felder werden in IL als "Literal" markiert, während readonly "initonly" ist.
Chris S.
quelle
11

Nur lesen : Wert geändert durch Ctor zur Laufzeit werden kann. Aber nicht durch die Mitgliedsfunktion

Konstante : Standardmäßig statisch. Der Wert kann von keiner Stelle aus geändert werden (Ctor, Funktion, Laufzeit usw. nirgendwo).

Yeasin Abedin Siam
quelle
Vielen Dank, dass ich nicht 4 Absätze nur für diese beiden Take-Aways gelesen habe ...
Don Cheadle
6

Ich glaube, ein constWert ist für alle Objekte gleich (und muss mit einem wörtlichen Ausdruck initialisiert werden), während er readonlyfür jede Instanziierung unterschiedlich sein kann ...

Daren Thomas
quelle
5

Eines der Teammitglieder in unserem Büro gab die folgenden Anweisungen zur Verwendung von const, static und readonly:

  • Verwenden Sie const, wenn Sie eine Variable eines Typs haben, von dem Sie zur Laufzeit wissen können (Zeichenfolgenliteral, int, double, enums, ...), dass alle Instanzen oder Konsumenten einer Klasse Zugriff darauf haben sollen, wo sich der Wert nicht ändern soll.
  • Verwenden Sie statisch, wenn Sie Daten haben, auf die alle Instanzen oder Konsumenten einer Klasse Zugriff haben sollen, auf die sich der Wert ändern kann.
  • Verwenden Sie statisch schreibgeschützt, wenn Sie eine Variable eines Typs haben, den Sie zur Laufzeit nicht kennen können (Objekte), auf die alle Instanzen oder Konsumenten einer Klasse Zugriff haben sollen, auf die sich der Wert nicht ändern soll.
  • Verwenden Sie schreibgeschützt, wenn Sie eine Variable auf Instanzebene haben, die Sie zum Zeitpunkt der Objekterstellung kennen und die sich nicht ändern sollte.

Eine letzte Anmerkung: Ein const-Feld ist statisch, aber die Umkehrung ist nicht wahr.

Scott Lawrence
quelle
1
Ich denke du meinst "unterhalten". Die Umkehrung wäre "ein nicht konstantes Feld ist nicht statisch". Welches kann oder kann nicht wahr sein. Die Umkehrung "ein statisches Feld ist (immer) const" ist nicht wahr.
Michael Blackburn
5

Sie sind beide konstant, aber eine Konstante ist auch zur Kompilierungszeit verfügbar. Dies bedeutet, dass ein Aspekt des Unterschieds darin besteht, dass Sie const-Variablen als Eingabe für Attributkonstruktoren verwenden können, jedoch keine schreibgeschützten Variablen.

Beispiel:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}
Hallgrim
quelle
5
  • wann zu verwenden constoderreadonly

    • const

      • Kompilierungszeitkonstante : Absolutkonstante , Wert wird während der Deklaration festgelegt, befindet sich im IL-Code selbst
    • readonly

      • Laufzeitkonstante : Kann im Konstruktor / Init über die Konfigurationsdatei festgelegt werden, dh nach der App.configInitialisierung kann sie nicht mehr geändert werden
Ryan Efendy
quelle
4

Mit const gekennzeichnete Variablen sind kaum mehr als stark typisierte # define-Makros. Zur Kompilierungszeit werden const-Variablenreferenzen durch Inline-Literalwerte ersetzt. Infolgedessen können auf diese Weise nur bestimmte integrierte primitive Werttypen verwendet werden. Nur schreibgeschützt markierte Variablen können in einem Konstruktor zur Laufzeit festgelegt werden, und ihre schreibgeschützte Schreibweise wird auch zur Laufzeit erzwungen. Dies ist mit geringfügigen Leistungskosten verbunden, bedeutet jedoch, dass Sie schreibgeschützt für jeden Typ (auch für Referenztypen) verwenden können.

Außerdem sind const-Variablen von Natur aus statisch, während schreibgeschützte Variablen bei Bedarf instanzspezifisch sein können.

Keil
quelle
Es wurde hinzugefügt, dass consts stark typisierte #define- Makros sind. Andernfalls können wir alle C- oder C ++ - Leute abschrecken. :-)
Jason Baker
4

CONST

  1. Das Schlüsselwort const kann auf Felder oder lokale Variablen angewendet werden
  2. Wir müssen das Feld const zum Zeitpunkt der Deklaration zuweisen
  3. Kein Speicher zugeordnet Da der const-Wert nach der Kompilierung in den IL-Code selbst eingebettet ist. Es ist so, als würde man alle Vorkommen der Variablen const finden und durch ihren Wert ersetzen. Daher hat der IL-Code nach der Kompilierung fest codierte Werte anstelle von const-Variablen
  4. Const in C # sind standardmäßig statisch.
  5. Der Wert ist für alle Objekte konstant
  6. Es gibt ein Problem mit der DLL-Versionierung - Dies bedeutet, dass jedes Mal, wenn wir eine öffentliche const-Variable oder -Eigenschaft ändern (tatsächlich sollte sie theoretisch nicht geändert werden), eine andere DLL oder Assembly, die diese Variable verwendet, neu erstellt werden muss
  7. Nur integrierte C # -Typen können als konstant deklariert werden
  8. Das Const-Feld kann nicht als ref- oder out-Parameter übergeben werden

Schreibgeschützt

  1. Das Schlüsselwort readonly gilt nur für Felder, nicht für lokale Variablen
  2. Wir können schreibgeschützte Felder zum Zeitpunkt der Deklaration oder im Konstruktor zuweisen, nicht in anderen Methoden.
  3. dynamischer Speicher für schreibgeschützte Felder zugewiesen und wir können den Wert zur Laufzeit erhalten.
  4. Readonly gehört zu dem Objekt, das so erstellt wurde, dass nur über eine Instanz der Klasse zugegriffen werden kann. Um es zum Klassenmitglied zu machen, müssen wir statisches Schlüsselwort hinzufügen, bevor wir schreibgeschützt sind.
  5. Der Wert kann je nach verwendetem Konstruktor unterschiedlich sein (da er zum Objekt der Klasse gehört).
  6. Wenn Sie einen nicht-primitiven Typ (Referenztyp) als schreibgeschützt deklarieren, ist nur die Referenz unveränderlich, nicht das darin enthaltene Objekt.
  7. Da der Wert zur Laufzeit abgerufen wird, gibt es kein Problem mit der DLL-Versionierung mit schreibgeschützten Feldern / Eigenschaften.
  8. Wir können schreibgeschütztes Feld als ref- oder out-Parameter im Konstruktorkontext übergeben.
Muhammad VP
quelle
3

Noch ein Gotcha .

Da const wirklich nur mit grundlegenden Datentypen funktioniert, fühlen Sie sich möglicherweise "gezwungen", ReadOnly zu verwenden, wenn Sie mit einer Klasse arbeiten möchten. Vorsicht vor der Falle! ReadOnly bedeutet, dass Sie das Objekt nicht durch ein anderes Objekt ersetzen können (Sie können es nicht auf ein anderes Objekt verweisen lassen). Jeder Prozess, der auf das Objekt verweist, kann die Werte im Objekt ändern !

Denken Sie also nicht, dass ReadOnly impliziert, dass ein Benutzer nichts ändern kann. In C # gibt es keine einfache Syntax, die verhindert, dass bei einer Instanziierung einer Klasse die internen Werte geändert werden (soweit ich weiß).

Mark T.
quelle
Ja, das ist eher ein allgemeines Thema. Wenn Sie eine get only-Eigenschaft haben, die eine Arrayliste verfügbar macht, können Sie die Arrayliste dennoch ändern. Sie können für diese Eigenschaft keine andere Arrayliste festlegen, aber Sie können den Benutzer nicht daran hindern, die Arrayliste zu ändern.
Gishu
3

A constmuss fest codiert sein , wo readonlydies im Konstruktor der Klasse festgelegt werden kann.

Greg
quelle
3

Es gibt einen bemerkenswerten Unterschied zwischen const- und schreibgeschützten Feldern in C # .Net

const ist standardmäßig statisch und muss mit einem konstanten Wert initialisiert werden, der später nicht mehr geändert werden kann. Wertänderungen sind auch in Konstruktoren nicht zulässig. Es kann nicht mit allen Datentypen verwendet werden. Zum Beispiel DateTime. Es kann nicht mit dem Datentyp DateTime verwendet werden.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

readonly kann als statisch deklariert werden, ist aber nicht erforderlich. Zum Zeitpunkt der Deklaration ist keine Initialisierung erforderlich. Sein Wert kann mit dem Konstruktor zugewiesen oder geändert werden. Es bietet also Vorteile, wenn es als Instanzklassenmitglied verwendet wird. Zwei verschiedene Instanziierungen können unterschiedliche Werte für das schreibgeschützte Feld haben. Zum Beispiel -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Dann kann das schreibgeschützte Feld wie folgt mit sofortigen spezifischen Werten initialisiert werden:

A objOne = new A(5);
A objTwo = new A(10);

Hier hat die Instanz objOne den Wert des schreibgeschützten Feldes 5 und objTwo den Wert 10. Dies ist mit const nicht möglich.

Chirag
quelle
2

Eine Konstante wird als Literalwert in den Consumer kompiliert, während die statische Zeichenfolge als Referenz auf den definierten Wert dient.

Versuchen Sie als Übung, eine externe Bibliothek zu erstellen und in einer Konsolenanwendung zu verwenden, ändern Sie dann die Werte in der Bibliothek und kompilieren Sie sie neu (ohne das Consumer-Programm neu zu kompilieren), legen Sie die DLL in dem Verzeichnis ab und führen Sie die EXE-Datei manuell aus dass sich die konstante Zeichenfolge nicht ändert.

Brett Ryan
quelle
Ich bezweifle aufrichtig, dass das wahr ist ... Ich werde nachsehen gehen.
ljs
Dies ist eine der 50 spezifischen Möglichkeiten, um Ihr C # zu verbessern - amazon.co.uk/Effective-Specific-Ways-Improve-Your/dp/0321245660/…
Russ Cam
@ Andrew Hare - ja, ich habe gerade nachgesehen. Ich bin sehr überrascht, das ist ein echtes Problem, ich bin wirklich sehr überrascht, erstaunt, dass das der Fall ist ...!
ljs
Ich lehne jedoch die Verwendung des Wortzeigers hier ab. Es ist kein Zeiger, es ist eine Referenz, und es gibt einen Unterschied in C #, da Sie nicht verwaltete Zeiger im unsicheren Modus bearbeiten können. Daher ist es wichtig, zwischen beiden zu unterscheiden.
ljs
2

Konstante

Wir müssen den Wert für das const-Feld bereitstellen, wenn es definiert ist. Der Compiler speichert dann den Wert der Konstante in den Metadaten der Assembly. Dies bedeutet, dass eine Konstante nur für den primitiven Typ wie Boolescher Wert, Zeichen, Byte usw. definiert werden kann. Konstanten werden immer als statische Elemente betrachtet, nicht als Instanzmitglieder.

Schreibgeschützt

Schreibgeschützte Felder können nur zur Laufzeit aufgelöst werden. Das heißt, wir können einen Wert für einen Wert mithilfe des Konstruktors für den Typ definieren, in dem das Feld deklariert ist. Die Überprüfung wird vom Compiler durchgeführt, dass schreibgeschützte Felder von keiner anderen Methode als dem Konstruktor beschrieben werden.

Mehr zu beiden hier in diesem Artikel erklärt

Vikram
quelle
1

Hauptsächlich; Sie können einem statischen schreibgeschützten Feld zur Laufzeit einen Wert für einen nicht konstanten Wert zuweisen, während einer Konstante ein konstanter Wert zugewiesen werden muss.

ljs
quelle
1

Const und Readonly sind ähnlich, aber sie sind nicht genau gleich. Ein const-Feld ist eine Konstante zur Kompilierungszeit, was bedeutet, dass dieser Wert zur Kompilierungszeit berechnet werden kann. Ein schreibgeschütztes Feld ermöglicht zusätzliche Szenarien, in denen während der Erstellung des Typs Code ausgeführt werden muss. Nach der Erstellung kann ein schreibgeschütztes Feld nicht mehr geändert werden.

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

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

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:

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 = r;
        green = g;
        blue = b;
    }
}

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. Indem wir einfach das schreibgeschützte Schlüsselwort in die Deklarationen einfügen, behalten wir die flexible Initialisierung bei und verhindern gleichzeitig, dass Client-Code herumwirbelt.

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 = r;
        green = g;
        blue = b;
    }
}

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:

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

und ein anderer Entwickler schrieb Code, der sich auf A stützte:

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

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.

Ramesh Rajendran
quelle
1

ReadOnly: Der Wert wird nur einmal vom Konstruktor der Klasse initialisiert.
const: kann in jeder Funktion nur einmal initialisiert werden

Donstack
quelle
1

Der Unterschied besteht darin, dass der Wert eines statischen schreibgeschützten Felds zur Laufzeit festgelegt wird, sodass es für verschiedene Programmausführungen einen anderen Wert haben kann. Der Wert eines const-Feldes wird jedoch auf eine Kompilierungszeitkonstante gesetzt.

Denken Sie daran: Bei Referenztypen verhindert der schreibgeschützte Modifikator in beiden Fällen (statisch und instanziell) nur, dass Sie dem Feld eine neue Referenz zuweisen. Insbesondere macht es das Objekt, auf das in der Referenz verwiesen wird, nicht unveränderlich.

Weitere Informationen finden Sie unter Häufig gestellte C # -Fragen zu diesem Thema: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx

Yonatan Nir
quelle
1

Konstante Variablen werden zur Kompilierungszeit deklariert und initialisiert. Der Wert kann nach den Stationen nicht mehr geändert werden. Schreibgeschützte Variablen werden nur vom statischen Konstruktor der Klasse initialisiert. Schreibgeschützt wird nur verwendet, wenn der Wert zur Laufzeit zugewiesen werden soll.

Omar AMEZOUG
quelle
1

Konst : Absoluter konstanter Wert während des Anwendungslebenszeit.

Readonly : Kann in der Laufzeit geändert werden.

Große Augen
quelle
1
Ihre Definition von "Readonly", die sich ändern kann, ist fehlerhaft. Ich denke mit "ändern" meinten Sie "setzen", wie "es kann zur Laufzeit gesetzt werden".
Ahmed
0

Eine Sache, die man zu dem hinzufügen sollte, was die Leute oben gesagt haben. Wenn Sie eine Assembly haben, die einen schreibgeschützten Wert enthält (z. B. readonly MaxFooCount = 4;), können Sie den Wert ändern, den aufrufende Assemblys sehen, indem Sie eine neue Version dieser Assembly mit einem anderen Wert versenden (z. B. readonly MaxFooCount = 5;).

Aber mit einer Konstante würde es beim Kompilieren des Anrufers in den Code des Anrufers gefaltet.

Wenn Sie dieses Niveau der C # -Kompetenz erreicht haben, sind Sie bereit für Bill Wagners Buch Effective C #: 50 spezifische Möglichkeiten zur Verbesserung Ihres C #, das diese Frage ausführlich beantwortet (und 49 andere Dinge).

Anthony
quelle