Risposte:
Sì, ma devi dichiararlo readonly
invece di const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
Il motivo è che const
può essere applicato solo a un campo il cui valore è noto in fase di compilazione. L'inizializzatore di array che hai mostrato non è un'espressione costante in C #, quindi produce un errore del compilatore.
La dichiarazione readonly
risolve questo problema perché il valore non è inizializzato fino al runtime (sebbene sia garantito che sia stato inizializzato prima della prima volta che l'array viene utilizzato).
A seconda di ciò che alla fine vuoi raggiungere, potresti anche considerare di dichiarare un enum:
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
avere qualsiasi somiglianza con la semantica richiesta.
static
non è necessario per farlo funzionare, è sufficiente aggiungere la possibilità di fare riferimento Titles
senza avere istanza, ma rimuovere la possibilità di modificare il valore per diverse istanze (ad es. Si può avere un costruttore con parametro a seconda di quale si cambia valore di quel readonly
campo).
Puoi dichiarare array come readonly
, ma tieni presente che puoi cambiare elemento readonly
dell'array.
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Prendi in considerazione l'uso di enum, come suggeriva Cody, o IList.
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
NOT readonly
...
Non è possibile creare un array 'const' perché gli array sono oggetti e possono essere creati solo in fase di esecuzione e le entità const vengono risolte al momento della compilazione.
Quello che puoi fare invece è dichiarare l'array come "di sola lettura". Ciò ha lo stesso effetto di const tranne che il valore può essere impostato in fase di esecuzione. Può essere impostato una sola volta ed è successivamente un valore di sola lettura (cioè const).
const int[] a = null;
che non è molto utile, ma in effetti un'istanza di una costante di array.
Da C # 6 puoi scriverlo come:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Vedi anche: C #: Il nuovo e migliorato C # 6.0 (in particolare il capitolo "Funzioni e proprietà del corpo di espressione")
Ciò renderà una proprietà statica di sola lettura, ma consentirà comunque di modificare il contenuto dell'array restituito, ma quando si chiama di nuovo la proprietà, si otterrà nuovamente l'array originale e inalterato.
Per chiarimenti, questo codice è uguale a (o in realtà una scorciatoia per):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
Si noti che c'è un aspetto negativo di questo approccio: un nuovo array è effettivamente istanziato su ogni riferimento, quindi se si utilizza un array molto grande, questa potrebbe non essere la soluzione più efficiente. Ma se riutilizzi lo stesso array (inserendolo ad esempio in un attributo privato), si aprirà nuovamente la possibilità di modificare il contenuto dell'array.
Se vuoi avere un array (o un elenco) immutabile, puoi anche usare:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Tuttavia, ciò comporta ancora il rischio di modifiche, in quanto è ancora possibile eseguirne il cast su una stringa [] e modificare il contenuto, in quanto tale:
((string[]) Titles)[1] = "French";
Titles[0]
, ad esempio - in effetti, il tentativo di assegnazione viene tranquillamente ignorato. Combinato con l'inefficienza di ricreare l'array ogni volta, mi chiedo se valga la pena mostrare questo approccio. Al contrario, il secondo approccio è efficiente e devi fare di tutto per sconfiggere l'immutabilità.
Se si dichiara un array dietro un'interfaccia IReadOnlyList, si ottiene un array costante con valori costanti dichiarati in fase di esecuzione:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Disponibile in .NET 4.5 e versioni successive.
Una soluzione .NET Framework v4.5 + che migliora la risposta di tdbeckett :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Nota: dato che la raccolta è concettualmente costante, può essere sensato farla static
dichiarare a livello di classe .
Quanto sopra:
Inizializza il campo di supporto implicito della proprietà una volta con l'array.
Si noti che { get; }
- vale a dire, dichiarando solo una proprietà getter - è ciò che rende la struttura in sé implicitamente sola lettura (cercando di coniugare readonly
con { get; }
è in realtà un errore di sintassi).
In alternativa, puoi semplicemente omettere { get; }
e aggiungere readonly
per creare un campo anziché una proprietà, come nella domanda, ma esporre i membri di dati pubblici come proprietà anziché come campi è una buona abitudine da formare.
Crea una struttura simile a un array (che consente l' accesso indicizzato ) che è di sola lettura (in modo concettualmente costante, una volta creata), sia rispetto a:
IReadOnlyList<T>
soluzione, in cui un (string[])
getto può essere utilizzata per ottenere l'accesso in scrittura agli elementi , come indicato nella risposta utile di mjepsen . IReadOnlyCollection<T>
interfaccia , che, nonostante la somiglianza nel nome alla classe ReadOnlyCollection
, non supporta nemmeno l' accesso indicizzato , rendendolo fondamentalmente inadatto per fornire un accesso simile a array.)IReadOnlyCollection
non supporta l'accesso indicizzato, quindi non può essere utilizzato qui. Inoltre, come IReadOnlyList
(che ha accesso indicizzato) è suscettibile alla manipolazione degli elementi eseguendo il cast su string[]
. In altre parole: ReadOnlyCollection
(su cui non è possibile eseguire il cast di un array di stringhe) è la soluzione più affidabile. Non usare un getter è un'opzione (e ho aggiornato la risposta per notare che), ma con i dati pubblici è probabilmente meglio attenersi a una proprietà.
Per le mie esigenze, definisco static
array, anziché impossibile const
e funziona:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
dall'esempio OP funziona, ma ciò (o la tua risposta) consente di modificare sia: Titles
istanza che qualsiasi valore. Quindi qual è il punto in questa risposta?
readonly
const
/ readonly
considerazione, semplicemente facendolo funzionare (come se const
fosse un errore di sintassi). Per alcune persone sembra essere una risposta preziosa (forse hanno anche provato a usare const
per errore?).
Potresti adottare un approccio diverso: definire una stringa costante per rappresentare l'array e quindi dividere la stringa in un array quando ne hai bisogno, ad es.
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
Questo approccio fornisce una costante che può essere memorizzata nella configurazione e convertita in un array quando necessario.
Per completezza, ora abbiamo anche ImmutableArrays a nostra disposizione. Questo dovrebbe essere veramente immutabile:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Richiede riferimento NuGet System.Collections.Immutable
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
Questo è un modo per fare quello che vuoi:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
È molto simile a fare un array di sola lettura.
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; non è necessario ricreare l'elenco su ogni recupero se lo si rende comunque ReadOnlyCollection.
Questa è l'unica risposta corretta. Al momento non puoi farlo.
Tutte le altre risposte suggeriscono di utilizzare variabili di sola lettura statiche simili , ma non uguali a, una costante. Una costante è codificata nell'assieme. Una variabile di sola lettura statica può essere impostata una volta, probabilmente quando un oggetto viene inizializzato.
Questi sono talvolta intercambiabili, ma non sempre.
In alternativa, per aggirare il problema degli elementi che possono essere modificati con un array di sola lettura, è possibile utilizzare invece una proprietà statica. (I singoli elementi possono ancora essere modificati, ma queste modifiche verranno apportate solo sulla copia locale dell'array.)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Naturalmente, questo non sarà particolarmente efficiente poiché ogni volta viene creato un nuovo array di stringhe.
La migliore alternativa:
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 };