Antworten:
Ja, aber Sie müssen es deklarieren readonly
anstatt const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Der Grund ist, dass const
nur auf ein Feld angewendet werden kann, dessen Wert zur Kompilierungszeit bekannt ist. Der angezeigte Array-Initialisierer ist kein konstanter Ausdruck in C #, daher wird ein Compilerfehler erzeugt.
Das Deklarieren readonly
löst dieses Problem, da der Wert erst zur Laufzeit initialisiert wird (obwohl er garantiert vor der ersten Verwendung des Arrays initialisiert wurde).
Je nachdem, was Sie letztendlich erreichen möchten, können Sie auch eine Aufzählung deklarieren:
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
Ähnlichkeit mit der angeforderten Semantik haben.
static
ist es nicht erforderlich, damit es funktioniert. Es wird lediglich die Möglichkeit hinzugefügt, Titles
ohne Instanz zu referenzieren , aber die Möglichkeit zu entfernen, den Wert für verschiedene Instanzen zu ändern (z. B. können Sie einen Konstruktor mit Parametern haben, je nachdem, welchen Wert Sie für dieses readonly
Feld ändern ).
Sie können das Array als deklarieren readonly
, aber denken Sie daran, dass Sie das Element des readonly
Arrays ändern können .
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Erwägen Sie die Verwendung von enum, wie Cody vorgeschlagen hat, oder IList.
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
NICHT readonly
...
Sie können kein 'const'-Array erstellen, da Arrays Objekte sind und nur zur Laufzeit erstellt werden können und const-Entitäten zur Kompilierungszeit aufgelöst werden.
Sie können stattdessen Ihr Array als "schreibgeschützt" deklarieren. Dies hat den gleichen Effekt wie const, außer dass der Wert zur Laufzeit festgelegt werden kann. Es kann nur einmal eingestellt werden und ist danach ein schreibgeschützter (dh konstanter) Wert.
const int[] a = null;
das nicht sehr nützliche, aber tatsächlich eine Instanz einer Array-Konstante.
Seit C # 6 können Sie es wie folgt schreiben:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Siehe auch: C #: Das neue und verbesserte C # 6.0 (insbesondere das Kapitel "Funktionen und Eigenschaften des Ausdrucks")
Dadurch wird eine schreibgeschützte statische Eigenschaft erstellt, Sie können jedoch weiterhin den Inhalt des zurückgegebenen Arrays ändern. Wenn Sie die Eigenschaft jedoch erneut aufrufen, erhalten Sie das ursprüngliche, unveränderte Array erneut.
Zur Verdeutlichung ist dieser Code derselbe wie (oder eigentlich eine Abkürzung für):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
Bitte beachten Sie, dass dieser Ansatz einen Nachteil hat: Bei jeder Referenz wird tatsächlich ein neues Array instanziiert. Wenn Sie also ein sehr großes Array verwenden, ist dies möglicherweise nicht die effizienteste Lösung. Wenn Sie jedoch dasselbe Array erneut verwenden (indem Sie es beispielsweise in ein privates Attribut einfügen), wird erneut die Möglichkeit eröffnet, den Inhalt des Arrays zu ändern.
Wenn Sie ein unveränderliches Array (oder eine Liste) haben möchten, können Sie auch Folgendes verwenden:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Dies birgt jedoch immer noch das Risiko von Änderungen, da Sie es immer noch in einen String [] umwandeln und den Inhalt als solchen ändern können:
((string[]) Titles)[1] = "French";
Titles[0]
Tatsächlich wird der Zuweisungsversuch stillschweigend ignoriert. In Kombination mit der Ineffizienz, das Array jedes Mal neu zu erstellen, frage ich mich, ob dieser Ansatz überhaupt eine Darstellung wert ist. Im Gegensatz dazu ist der zweite Ansatz effizient und Sie müssen alles tun, um die Unveränderlichkeit zu besiegen.
Wenn Sie ein Array hinter einer IReadOnlyList-Schnittstelle deklarieren, erhalten Sie ein konstantes Array mit konstanten Werten, das zur Laufzeit deklariert wird:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Verfügbar in .NET 4.5 und höher.
Eine .NET Framework v4.5 + -Lösung , die die Antwort von tdbeckett verbessert :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Hinweis: Da die Sammlung konzeptionell konstant ist, kann es sinnvoll sein static
, sie in der Klasse zu deklarieren .
Obenstehendes:
Initialisiert das implizite Sicherungsfeld der Eigenschaft einmal mit dem Array.
Beachten Sie, dass { get; }
- das heißt, erklärt nur eine Eigenschaft Getter - ist das, was die Eigenschaft macht sich implizit nur schreib (versucht zu kombinieren readonly
mit { get; }
ist eigentlich ein Syntaxfehler).
Alternativ können Sie das Feld weglassen { get; }
und hinzufügen readonly
, um ein Feld anstelle einer Eigenschaft zu erstellen , wie in der Frage beschrieben. Es ist jedoch eine gute Angewohnheit , öffentliche Datenelemente als Eigenschaften und nicht als Felder bereitzustellen.
Erstellt eine Array- ähnliche Struktur (die einen indizierten Zugriff ermöglicht ), die wirklich und robust schreibgeschützt ist (konzeptionell konstant, sobald sie erstellt wurde), sowohl in Bezug auf:
IReadOnlyList<T>
Lösung, bei der ein (string[])
Guss verwendet werden kann , Schreibzugriff auf die Elemente zu gewinnen , wie es in gezeigt mjepsen die hilfreiche Antwort . IReadOnlyCollection<T>
Schnittstelle , die trotz der Namensähnlichkeit zu Klasse ReadOnlyCollection
, nicht unterstützt sogar indexierten Zugang , es grundsätzlich nicht geeignet für die Bereitstellung von Array-ähnlichem Zugriff zu machen.)IReadOnlyCollection
Unterstützt leider keinen indizierten Zugriff, daher kann er hier nicht verwendet werden. Darüber hinaus ist es wie IReadOnlyList
(das über einen indizierten Zugriff verfügt) anfällig für Elementmanipulationen durch Zurücksetzen auf string[]
. Mit anderen Worten: ReadOnlyCollection
(in die Sie kein String-Array umwandeln können) ist die robusteste Lösung. Es ist eine Option, keinen Getter zu verwenden (und ich habe die Antwort aktualisiert, um dies zu beachten), aber bei öffentlichen Daten ist es wahrscheinlich besser, bei einer Eigenschaft zu bleiben.
Für meine Bedürfnisse definiere ich static
Array, anstatt unmöglich const
und es funktioniert:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
aus dem OP-Beispiel funktioniert auch, aber das (oder Ihre Antwort) ermöglicht es, sowohl die Titles
Instanz als auch einen beliebigen Wert zu ändern . Worum geht es in dieser Antwort?
readonly
const
/ readonly
Überlegungen, einfach machen es funktioniert (wie wenn const
war ein Syntaxfehler). Für manche Menschen scheint es eine wertvolle Antwort zu sein (vielleicht haben sie auch versucht, sie versehentlich zu verwenden const
?).
Sie können einen anderen Ansatz wählen: Definieren Sie eine konstante Zeichenfolge, um Ihr Array darzustellen, und teilen Sie die Zeichenfolge dann bei Bedarf in ein Array auf, z
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
Mit diesem Ansatz erhalten Sie eine Konstante, die in der Konfiguration gespeichert und bei Bedarf in ein Array konvertiert werden kann.
Der Vollständigkeit halber verfügen wir jetzt auch über ImmutableArrays. Dies sollte wirklich unveränderlich sein:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Benötigt System.Collections.Immutable NuGet-Referenz
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
So können Sie tun, was Sie wollen:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
Es ist sehr ähnlich zu einem schreibgeschützten Array.
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; Sie müssen die Liste nicht bei jedem Abruf neu erstellen, wenn Sie sie trotzdem zu einer ReadOnlyCollection machen.
Dies ist die einzig richtige Antwort. Sie können dies derzeit nicht tun.
Alle anderen Antworten schlagen vor, statische schreibgeschützte Variablen zu verwenden, die ähnlich sind , die einer Konstanten , aber nicht identisch sind. Eine Konstante ist in der Baugruppe fest codiert. Eine statische schreibgeschützte Variable kann einmal eingestellt werden, wahrscheinlich wenn ein Objekt initialisiert wird.
Diese sind manchmal austauschbar, aber nicht immer.
Alternativ können Sie stattdessen eine statische Eigenschaft verwenden, um das Problem zu umgehen, dass Elemente mit einem schreibgeschützten Array geändert werden können. (Die einzelnen Elemente können weiterhin geändert werden, diese Änderungen werden jedoch nur auf der lokalen Kopie des Arrays vorgenommen.)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Dies ist natürlich nicht besonders effizient, da jedes Mal ein neues String-Array erstellt wird.
Beste Alternative:
public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };