Respuestas:
Sí, pero debe declararlo en readonly
lugar de const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
La razón es que const
solo se puede aplicar a un campo cuyo valor se conoce en tiempo de compilación. El inicializador de matriz que ha mostrado no es una expresión constante en C #, por lo que produce un error de compilación.
Declarar que readonly
resuelve ese problema porque el valor no se inicializa hasta el tiempo de ejecución (aunque se garantiza que se ha inicializado antes de la primera vez que se usa la matriz).
Dependiendo de qué es lo que finalmente desea lograr, también puede considerar declarar una enumeración:
public enum Titles { German, Spanish, Corrects, Wrongs };
readonly static
para tener algún parecido con la semántica solicitada.
static
no es necesario que funcione, solo agrega la posibilidad de hacer referencia Titles
sin tener una instancia, pero elimina la posibilidad de cambiar el valor para diferentes instancias (por ejemplo, puede tener un constructor con un parámetro dependiendo de cuál cambie el valor de ese readonly
campo).
Puede declarar la matriz como readonly
, pero tenga en cuenta que puede cambiar el elemento de la readonly
matriz.
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
Considere usar enum, como sugirió Cody, o IList.
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
const
NO readonly
...
No puede crear una matriz 'const' porque las matrices son objetos y solo se pueden crear en tiempo de ejecución y las entidades const se resuelven en tiempo de compilación.
Lo que puede hacer en su lugar es declarar su matriz como "solo lectura". Esto tiene el mismo efecto que const, excepto que el valor se puede establecer en tiempo de ejecución. Solo se puede configurar una vez y luego es un valor de solo lectura (es decir, constante).
const int[] a = null;
que no es muy útil, pero sí una instancia de una constante de matriz.
Desde C # 6 puedes escribirlo como:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Ver también: C #: El nuevo y mejorado C # 6.0 (específicamente el capítulo "Funciones y propiedades con cuerpo de expresión")
Esto creará una propiedad estática de solo lectura, pero aún así le permitirá alterar el contenido de la matriz devuelta, pero cuando vuelva a llamar a la propiedad, volverá a obtener la matriz original sin alterar.
Para aclarar, este código es el mismo que (o en realidad es una abreviatura de):
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
Tenga en cuenta que este enfoque tiene un inconveniente: en realidad, se crea una nueva matriz en todas y cada una de las referencias, por lo que si está utilizando una matriz muy grande, esta podría no ser la solución más eficiente. Pero si reutiliza la misma matriz (poniéndola en un atributo privado, por ejemplo), volverá a abrir la posibilidad de cambiar el contenido de la matriz.
Si desea tener una matriz (o lista) inmutable, también puede usar:
public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
Pero, esto todavía tiene el riesgo de cambios, ya que aún puede volver a convertirlo en una cadena [] y alterar el contenido, como tal:
((string[]) Titles)[1] = "French";
Titles[0]
, por ejemplo, en efecto, el intento de asignación se ignora silenciosamente. Combinado con la ineficiencia de recrear la matriz cada vez, me pregunto si vale la pena mostrar este enfoque. Por el contrario, el segundo enfoque es eficiente, y tienes que salir de tu camino para vencer la inmutabilidad.
Si declara una matriz detrás de una interfaz IReadOnlyList, obtiene una matriz constante con valores constantes que se declara en tiempo de ejecución:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
Disponible en .NET 4.5 y superior.
Una solución .NET Framework v4.5 + que mejora la respuesta de tdbeckett :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
Nota: Dado que la colección es conceptualmente constante, puede tener sentido static
declararla a nivel de clase .
Lo anterior:
Inicializa el campo de respaldo implícito de la propiedad una vez con la matriz.
Tenga en cuenta que { get; }
- es decir, declarar solamente una propiedad getter - es lo que hace que la propiedad en sí implícitamente sólo lectura (tratando de combinar readonly
con la { get; }
realidad, es un error de sintaxis).
Alternativamente, puede omitir { get; }
y agregar readonly
para crear un campo en lugar de una propiedad, como en la pregunta, pero exponer a los miembros de datos públicos como propiedades en lugar de campos es un buen hábito para formar.
Crea una estructura de tipo matriz (que permite el acceso indexado ) que es verdadera y robustamente de solo lectura (conceptualmente constante, una vez creada), ambos con respecto a:
IReadOnlyList<T>
solución, donde un (string[])
reparto se puede utilizar para obtener acceso de escritura a los elementos , como se muestra en la útil respuesta de mjepsen . IReadOnlyCollection<T>
interfaz , que, a pesar de la similitud en el nombre a la clase ReadOnlyCollection
, ni siquiera admite el acceso indexado , lo que lo hace fundamentalmente inadecuado para proporcionar acceso tipo matriz).IReadOnlyCollection
no admite acceso indexado, por lo que no se puede usar aquí. Además, like IReadOnlyList
(que tiene acceso indexado) es susceptible a la manipulación de elementos al volver a enviarlos string[]
. En otras palabras: ReadOnlyCollection
(a la que no puede convertir una matriz de cadenas) es la solución más sólida. No usar un captador es una opción (y he actualizado la respuesta para tener en cuenta eso), pero con los datos públicos probablemente sea mejor quedarse con una propiedad.
Para mis necesidades defino static
matriz, en lugar de imposible const
y funciona:
public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
const
del ejemplo OP también funciona, pero eso (o su respuesta) permite cambiar tanto: Titles
instancia como cualquier valor. Entonces, ¿cuál es el punto en esta respuesta?
readonly
const
/ readonly
consideración, simplemente haciéndolo funcionar (como si const
fuera un error de sintaxis). Para algunas personas, parece ser una respuesta valiosa (¿tal vez también intentaron usarla const
por error?).
Podría adoptar un enfoque diferente: defina una cadena constante para representar su matriz y luego divida la cadena en una matriz cuando la necesite, p. Ej.
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
Este enfoque le proporciona una constante que puede almacenarse en la configuración y convertirse en una matriz cuando sea necesario.
En aras de la exhaustividad, ahora también tenemos ImmutableArrays a nuestra disposición. Esto debería ser realmente inmutable:
public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
Requiere System.Collections.Immutable NuGet reference
https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx
Esta es una manera de hacer lo que quieres:
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 muy similar a hacer una matriz de solo lectura.
public static readonly ReadOnlyCollection<String> Titles = new List<String> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
; no es necesario volver a crear la lista en cada recuperación si la convierte en una ReadOnlyCollection de todos modos.
Esta es la única respuesta correcta. Actualmente no puedes hacer esto.
Todas las otras respuestas sugieren usar variables estáticas de solo lectura que son similares , pero no iguales a una constante. Una constante está codificada en el ensamblaje. Una variable de solo lectura estática se puede configurar una vez, probablemente a medida que se inicializa un objeto.
Estos a veces son intercambiables, pero no siempre.
Como alternativa, para solucionar el problema de elementos que se pueden modificar con una matriz de solo lectura, puede usar una propiedad estática en su lugar. (Los elementos individuales aún se pueden cambiar, pero estos cambios solo se realizarán en la copia local de la matriz).
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
Por supuesto, esto no será particularmente eficiente ya que cada vez se crea una nueva matriz de cadenas.
Mejor 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 };