const
und readonly
sind ähnlich, aber sie sind nicht genau gleich.
Ein const
Feld ist eine Konstante zur Kompilierungszeit, dh dieser Wert kann zur Kompilierungszeit berechnet werden. Ein readonly
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:
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, green, blue) = (r, g, 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.
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.
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 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.
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.