Declare una matriz de const

¿Es posible escribir algo similar a lo siguiente?

public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" }; 

Sí, pero debe declararlo de manera readonly vez de const :

 public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" }; 

El motivo es que const solo se puede aplicar a un campo cuyo valor se conoce en tiempo de comstackción. El inicializador de matriz que ha mostrado no es una expresión constante en C #, por lo que produce un error de comstackción.

Declararlo readonly resuelve el problema porque el valor no se inicializa hasta el tiempo de ejecución (aunque está garantizado que se ha inicializado antes de la primera vez que se utiliza 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 }; 

Puede declarar una matriz como de readonly , pero tenga en cuenta que puede cambiar el elemento de una matriz de readonly .

 public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" }; ... Titles[0] = "bla"; 

Considere usar enum, como sugirió Cody, o IList.

 public readonly IList ITitles = new List {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly(); 

No puede crear una matriz ‘const’ porque las matrices son objetos y solo pueden crearse en tiempo de ejecución y las entidades const se resuelven en tiempo de comstackción.

Lo que puede hacer en su lugar es declarar su matriz como “de solo lectura”. Esto tiene el mismo efecto que const, excepto que el valor puede establecerse en tiempo de ejecución. Solo se puede establecer una vez y luego es un valor de solo lectura (es decir, const).

Para mis necesidades, defino static matriz static , en lugar de const imposible, y funciona: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

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 configuración y convertirse en una matriz cuando sea necesario.

Alastair

Desde C # 6 puedes escribirlo así:

 public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" }; 

Vea también: C #: El C # 6.0 nuevo y mejorado (específicamente el capítulo “Funciones y propiedades corporales de expresión”)

Esto creará una propiedad estática de solo lectura, pero aún le permitirá alterar el contenido de la matriz devuelta, pero cuando vuelva a llamar a la propiedad, obtendrá nuevamente la matriz original sin modificaciones.

Para aclarar, este código es el mismo que (o en realidad una forma abreviada de):

 public static string[] Titles { get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; } } 

Tenga en cuenta que hay una desventaja de este enfoque: una nueva matriz se instancia en realidad en cada referencia, por lo que si está utilizando una matriz muy grande, esta podría no ser la solución más eficiente. Pero si vuelve a utilizar la misma matriz (poniéndola en un atributo privado, por ejemplo), nuevamente se abrirá la posibilidad de cambiar el contenido de la matriz.

Si quieres tener una matriz inmutable (o una lista) también puedes usar:

 public static IReadOnlyList Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" }; 

Sin embargo, esto todavía tiene un riesgo de cambios, ya que aún puede volver a lanzarlo a una cadena [] y modificar el contenido, como tal:

 ((string[]) Titles)[1] = "French"; 

Esta es una forma de hacer lo que quieras:

 using System; using System.Collections.ObjectModel; using System.Collections.Generic; public ReadOnlyCollection Titles { get { return new List { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}} 

Es muy similar a hacer una matriz de solo lectura.

Una solución .NET Framework v4.5 + que mejora la respuesta de tdbeckett :

 using System.Collections.ObjectModel; // ... public ReadOnlyCollection Titles { get; } = new ReadOnlyCollection( new string[] { "German", "Spanish", "Corrects", "Wrongs" } ); 

Nota: Dado que la colección es conceptualmente constante, puede tener sentido hacerla static para declararla en el 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; } { get; } – es decir, declarar solo un getter de propiedad – es lo que hace que la propiedad sea implícitamente de solo lectura (intentar combinar readonly con { get; } es en realidad un error de syntax).

    • Alternativamente, puedes omitir { get; } { get; } y agregue 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 similar a una matriz (que permite el acceso indexado) que es verdadera y robustamente de solo lectura (conceptualmente, constante, una vez creada), ambas con respecto a:

    • prevenir la modificación de la colección (como eliminar o agregar elementos o reemplazar la colección como un todo)
    • evitando la modificación de elementos individuales.
      (Incluso la modificación indirecta no es posible, a diferencia de una IReadOnlyList , donde un molde (string[]) se puede usar para obtener acceso de escritura a los elementos, como se muestra en la útil respuesta de mjepsen .
      La misma vulnerabilidad se aplica a la IReadOnlyCollection , que, a pesar de su similitud de nombre con la clase ReadOnlyCollection , ni siquiera es compatible con el acceso indexado , por lo que es fundamentalmente inadecuado para proporcionar acceso tipo array.

Si declara una matriz detrás de una interfaz IReadOnlyList, obtiene una matriz constante con valores constantes que se declaran en tiempo de ejecución:

 public readonly IReadOnlyList Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" }; 

Disponible en .NET 4.5 y superior.

Creo que solo puedes hacer que sea de solo lectura.

Las matrices son probablemente una de esas cosas que solo se pueden evaluar en tiempo de ejecución. Las constantes deben evaluarse en tiempo de comstackción. Intenta usar “readonly” en lugar de “const”.

Como alternativa, para evitar el problema de los elementos que se pueden modificar con una matriz de solo lectura, puede usar una propiedad estática. (Los elementos individuales todavía 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 se crea una nueva matriz de cadenas cada vez.

Para completar, ahora también tenemos InmutableArrays a nuestra disposición. Esto debería ser verdaderamente inmutable:

 public readonly static ImmutableArray Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" }); 

Requiere referencias de System.Collections.Immutable NuGet

https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx